diff --git a/Jamroot b/Jamroot index c19b404..c979d80 100644 --- a/Jamroot +++ b/Jamroot @@ -144,7 +144,7 @@ import option ; import tools/boost\_install/boost-install ; path-constant BOOST_ROOT : . ; -constant BOOST_VERSION : 1.82.0 ; +constant BOOST_VERSION : 1.83.0 ; constant BOOST_JAMROOT_MODULE : $(__name__) ; # Allow subprojects to simply `import config : requires ;` to get access to the requires rule diff --git a/Readme.md b/Readme.md index 92ea758..b981446 100644 --- a/Readme.md +++ b/Readme.md @@ -16,7 +16,7 @@ To update the Boost version (or to add a new library) follow these steps: ``` - Store the boost directory in a variable for later use: `$boost_dir = $pwd`. - - Add bcp to your path: `$env:Path += ";$boost_dir\bin.v2\tools\bcp\msvc-14.2\release\link-static\threading-multi"` (The correct output path should be printed by b2 during the build.) + - Add bcp to your path: `$env:Path += ";$boost_dir\bin.v2\tools\bcp\msvc-14.3\release\link-static\threading-multi"` (The correct output path should be printed by b2 during the build.) - `cd` to this repo's directory (`...\externals\boost\`) - Remove the existing boost from the repo: `rm -r boost` (This is only necessary if doing a Boost version upgrade, in case they removed any files in the new version.) - Run `.\build.cmd $boost_dir` to build a new trimmed down distro. diff --git a/boost/algorithm/string/case_conv.hpp b/boost/algorithm/string/case_conv.hpp deleted file mode 100644 index 683340b..0000000 --- a/boost/algorithm/string/case_conv.hpp +++ /dev/null @@ -1,176 +0,0 @@ -// Boost string_algo library case_conv.hpp header file ---------------------------// - -// Copyright Pavol Droba 2002-2003. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/ for updates, documentation, and revision history. - -#ifndef BOOST_STRING_CASE_CONV_HPP -#define BOOST_STRING_CASE_CONV_HPP - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -/*! \file - Defines sequence case-conversion algorithms. - Algorithms convert each element in the input sequence to the - desired case using provided locales. -*/ - -namespace boost { - namespace algorithm { - -// to_lower -----------------------------------------------// - - //! Convert to lower case - /*! - Each element of the input sequence is converted to lower - case. The result is a copy of the input converted to lower case. - It is returned as a sequence or copied to the output iterator. - - \param Output An output iterator to which the result will be copied - \param Input An input range - \param Loc A locale used for conversion - \return - An output iterator pointing just after the last inserted character or - a copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - - */ - template - inline OutputIteratorT - to_lower_copy( - OutputIteratorT Output, - const RangeT& Input, - const std::locale& Loc=std::locale()) - { - return ::boost::algorithm::detail::transform_range_copy( - Output, - ::boost::as_literal(Input), - ::boost::algorithm::detail::to_lowerF< - typename range_value::type >(Loc)); - } - - //! Convert to lower case - /*! - \overload - */ - template - inline SequenceT to_lower_copy( - const SequenceT& Input, - const std::locale& Loc=std::locale()) - { - return ::boost::algorithm::detail::transform_range_copy( - Input, - ::boost::algorithm::detail::to_lowerF< - typename range_value::type >(Loc)); - } - - //! Convert to lower case - /*! - Each element of the input sequence is converted to lower - case. The input sequence is modified in-place. - - \param Input A range - \param Loc a locale used for conversion - */ - template - inline void to_lower( - WritableRangeT& Input, - const std::locale& Loc=std::locale()) - { - ::boost::algorithm::detail::transform_range( - ::boost::as_literal(Input), - ::boost::algorithm::detail::to_lowerF< - typename range_value::type >(Loc)); - } - -// to_upper -----------------------------------------------// - - //! Convert to upper case - /*! - Each element of the input sequence is converted to upper - case. The result is a copy of the input converted to upper case. - It is returned as a sequence or copied to the output iterator - - \param Output An output iterator to which the result will be copied - \param Input An input range - \param Loc A locale used for conversion - \return - An output iterator pointing just after the last inserted character or - a copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template - inline OutputIteratorT - to_upper_copy( - OutputIteratorT Output, - const RangeT& Input, - const std::locale& Loc=std::locale()) - { - return ::boost::algorithm::detail::transform_range_copy( - Output, - ::boost::as_literal(Input), - ::boost::algorithm::detail::to_upperF< - typename range_value::type >(Loc)); - } - - //! Convert to upper case - /*! - \overload - */ - template - inline SequenceT to_upper_copy( - const SequenceT& Input, - const std::locale& Loc=std::locale()) - { - return ::boost::algorithm::detail::transform_range_copy( - Input, - ::boost::algorithm::detail::to_upperF< - typename range_value::type >(Loc)); - } - - //! Convert to upper case - /*! - Each element of the input sequence is converted to upper - case. The input sequence is modified in-place. - - \param Input An input range - \param Loc a locale used for conversion - */ - template - inline void to_upper( - WritableRangeT& Input, - const std::locale& Loc=std::locale()) - { - ::boost::algorithm::detail::transform_range( - ::boost::as_literal(Input), - ::boost::algorithm::detail::to_upperF< - typename range_value::type >(Loc)); - } - - } // namespace algorithm - - // pull names to the boost namespace - using algorithm::to_lower; - using algorithm::to_lower_copy; - using algorithm::to_upper; - using algorithm::to_upper_copy; - -} // namespace boost - -#endif // BOOST_STRING_CASE_CONV_HPP diff --git a/boost/algorithm/string/detail/case_conv.hpp b/boost/algorithm/string/detail/case_conv.hpp deleted file mode 100644 index 188602a..0000000 --- a/boost/algorithm/string/detail/case_conv.hpp +++ /dev/null @@ -1,130 +0,0 @@ -// Boost string_algo library string_funct.hpp header file ---------------------------// - -// Copyright Pavol Droba 2002-2003. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/ for updates, documentation, and revision history. - -#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP -#define BOOST_STRING_CASE_CONV_DETAIL_HPP - -#include -#include -#include - -#include -#include -#include -#include - -namespace boost { - namespace algorithm { - namespace detail { - -// case conversion functors -----------------------------------------------// - -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -#pragma warning(push) -#pragma warning(disable:4512) //assignment operator could not be generated -#endif - - // a tolower functor - template - struct to_lowerF - { - typedef CharT argument_type; - typedef CharT result_type; - // Constructor - to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {} - - // Operation - CharT operator ()( CharT Ch ) const - { - #if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL) - return std::tolower( static_cast::type> ( Ch )); - #else - return std::tolower( Ch, *m_Loc ); - #endif - } - private: - const std::locale* m_Loc; - }; - - // a toupper functor - template - struct to_upperF - { - typedef CharT argument_type; - typedef CharT result_type; - // Constructor - to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {} - - // Operation - CharT operator ()( CharT Ch ) const - { - #if defined(BOOST_BORLANDC) && (BOOST_BORLANDC >= 0x560) && (BOOST_BORLANDC <= 0x564) && !defined(_USE_OLD_RW_STL) - return std::toupper( static_cast::type> ( Ch )); - #else - return std::toupper( Ch, *m_Loc ); - #endif - } - private: - const std::locale* m_Loc; - }; - -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -#pragma warning(pop) -#endif - -// algorithm implementation ------------------------------------------------------------------------- - - // Transform a range - template - OutputIteratorT transform_range_copy( - OutputIteratorT Output, - const RangeT& Input, - FunctorT Functor) - { - return std::transform( - ::boost::begin(Input), - ::boost::end(Input), - Output, - Functor); - } - - // Transform a range (in-place) - template - void transform_range( - const RangeT& Input, - FunctorT Functor) - { - std::transform( - ::boost::begin(Input), - ::boost::end(Input), - ::boost::begin(Input), - Functor); - } - - template - inline SequenceT transform_range_copy( - const RangeT& Input, - FunctorT Functor) - { - return SequenceT( - ::boost::make_transform_iterator( - ::boost::begin(Input), - Functor), - ::boost::make_transform_iterator( - ::boost::end(Input), - Functor)); - } - - } // namespace detail - } // namespace algorithm -} // namespace boost - - -#endif // BOOST_STRING_CASE_CONV_DETAIL_HPP diff --git a/boost/algorithm/string/erase.hpp b/boost/algorithm/string/erase.hpp deleted file mode 100644 index 6883790..0000000 --- a/boost/algorithm/string/erase.hpp +++ /dev/null @@ -1,844 +0,0 @@ -// Boost string_algo library erase.hpp header file ---------------------------// - -// Copyright Pavol Droba 2002-2006. -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/ for updates, documentation, and revision history. - -#ifndef BOOST_STRING_ERASE_HPP -#define BOOST_STRING_ERASE_HPP - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -/*! \file - Defines various erase algorithms. Each algorithm removes - part(s) of the input according to a searching criteria. -*/ - -namespace boost { - namespace algorithm { - -// erase_range -------------------------------------------------------// - - //! Erase range algorithm - /*! - Remove the given range from the input. The result is a modified copy of - the input. It is returned as a sequence or copied to the output iterator. - - \param Output An output iterator to which the result will be copied - \param Input An input sequence - \param SearchRange A range in the input to be removed - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template - inline OutputIteratorT erase_range_copy( - OutputIteratorT Output, - const RangeT& Input, - const iterator_range< - BOOST_STRING_TYPENAME - range_const_iterator::type>& SearchRange ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::range_finder(SearchRange), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase range algorithm - /*! - \overload - */ - template - inline SequenceT erase_range_copy( - const SequenceT& Input, - const iterator_range< - BOOST_STRING_TYPENAME - range_const_iterator::type>& SearchRange ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::range_finder(SearchRange), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase range algorithm - /*! - Remove the given range from the input. - The input sequence is modified in-place. - - \param Input An input sequence - \param SearchRange A range in the input to be removed - */ - template - inline void erase_range( - SequenceT& Input, - const iterator_range< - BOOST_STRING_TYPENAME - range_iterator::type>& SearchRange ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::range_finder(SearchRange), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_first --------------------------------------------------------// - - //! Erase first algorithm - /*! - Remove the first occurrence of the substring from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT erase_first_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase first algorithm - /*! - \overload - */ - template - inline SequenceT erase_first_copy( - const SequenceT& Input, - const RangeT& Search ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase first algorithm - /*! - Remove the first occurrence of the substring from the input. - The input sequence is modified in-place. - - \param Input An input string - \param Search A substring to be searched for. - */ - template - inline void erase_first( - SequenceT& Input, - const RangeT& Search ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_first ( case insensitive ) ------------------------------------// - - //! Erase first algorithm ( case insensitive ) - /*! - Remove the first occurrence of the substring from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - Searching is case insensitive. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for - \param Loc A locale used for case insensitive comparison - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT ierase_first_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase first algorithm ( case insensitive ) - /*! - \overload - */ - template - inline SequenceT ierase_first_copy( - const SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase first algorithm ( case insensitive ) - /*! - Remove the first occurrence of the substring from the input. - The input sequence is modified in-place. Searching is case insensitive. - - \param Input An input string - \param Search A substring to be searched for - \param Loc A locale used for case insensitive comparison - */ - template - inline void ierase_first( - SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_last --------------------------------------------------------// - - //! Erase last algorithm - /*! - Remove the last occurrence of the substring from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for. - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT erase_last_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::last_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase last algorithm - /*! - \overload - */ - template - inline SequenceT erase_last_copy( - const SequenceT& Input, - const RangeT& Search ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::last_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase last algorithm - /*! - Remove the last occurrence of the substring from the input. - The input sequence is modified in-place. - - \param Input An input string - \param Search A substring to be searched for - */ - template - inline void erase_last( - SequenceT& Input, - const RangeT& Search ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::last_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_last ( case insensitive ) ------------------------------------// - - //! Erase last algorithm ( case insensitive ) - /*! - Remove the last occurrence of the substring from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - Searching is case insensitive. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for - \param Loc A locale used for case insensitive comparison - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT ierase_last_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::last_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase last algorithm ( case insensitive ) - /*! - \overload - */ - template - inline SequenceT ierase_last_copy( - const SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::last_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase last algorithm ( case insensitive ) - /*! - Remove the last occurrence of the substring from the input. - The input sequence is modified in-place. Searching is case insensitive. - - \param Input An input string - \param Search A substring to be searched for - \param Loc A locale used for case insensitive comparison - */ - template - inline void ierase_last( - SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::last_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_nth --------------------------------------------------------------------// - - //! Erase nth algorithm - /*! - Remove the Nth occurrence of the substring in the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for - \param Nth An index of the match to be replaced. The index is 0-based. - For negative N, matches are counted from the end of string. - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT erase_nth_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search, - int Nth ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::nth_finder(Search, Nth), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase nth algorithm - /*! - \overload - */ - template - inline SequenceT erase_nth_copy( - const SequenceT& Input, - const RangeT& Search, - int Nth ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::nth_finder(Search, Nth), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase nth algorithm - /*! - Remove the Nth occurrence of the substring in the input. - The input sequence is modified in-place. - - \param Input An input string - \param Search A substring to be searched for. - \param Nth An index of the match to be replaced. The index is 0-based. - For negative N, matches are counted from the end of string. - */ - template - inline void erase_nth( - SequenceT& Input, - const RangeT& Search, - int Nth ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::nth_finder(Search, Nth), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_nth ( case insensitive ) ---------------------------------------------// - - //! Erase nth algorithm ( case insensitive ) - /*! - Remove the Nth occurrence of the substring in the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - Searching is case insensitive. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for. - \param Nth An index of the match to be replaced. The index is 0-based. - For negative N, matches are counted from the end of string. - \param Loc A locale used for case insensitive comparison - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT ierase_nth_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search, - int Nth, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase nth algorithm - /*! - \overload - */ - template - inline SequenceT ierase_nth_copy( - const SequenceT& Input, - const RangeT& Search, - int Nth, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), - empty_formatter(Input) ); - } - - //! Erase nth algorithm - /*! - Remove the Nth occurrence of the substring in the input. - The input sequence is modified in-place. Searching is case insensitive. - - \param Input An input string - \param Search A substring to be searched for. - \param Nth An index of the match to be replaced. The index is 0-based. - For negative N, matches are counted from the end of string. - \param Loc A locale used for case insensitive comparison - */ - template - inline void ierase_nth( - SequenceT& Input, - const RangeT& Search, - int Nth, - const std::locale& Loc=std::locale() ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - -// erase_all --------------------------------------------------------// - - //! Erase all algorithm - /*! - Remove all the occurrences of the string from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - - - \param Output An output iterator to which the result will be copied - \param Input An input sequence - \param Search A substring to be searched for. - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT erase_all_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search ) - { - return ::boost::algorithm::find_format_all_copy( - Output, - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase all algorithm - /*! - \overload - */ - template - inline SequenceT erase_all_copy( - const SequenceT& Input, - const RangeT& Search ) - { - return ::boost::algorithm::find_format_all_copy( - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase all algorithm - /*! - Remove all the occurrences of the string from the input. - The input sequence is modified in-place. - - \param Input An input string - \param Search A substring to be searched for. - */ - template - inline void erase_all( - SequenceT& Input, - const RangeT& Search ) - { - ::boost::algorithm::find_format_all( - Input, - ::boost::algorithm::first_finder(Search), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_all ( case insensitive ) ------------------------------------// - - //! Erase all algorithm ( case insensitive ) - /*! - Remove all the occurrences of the string from the input. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - Searching is case insensitive. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param Search A substring to be searched for - \param Loc A locale used for case insensitive comparison - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename Range1T, - typename Range2T> - inline OutputIteratorT ierase_all_copy( - OutputIteratorT Output, - const Range1T& Input, - const Range2T& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_all_copy( - Output, - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase all algorithm ( case insensitive ) - /*! - \overload - */ - template - inline SequenceT ierase_all_copy( - const SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - return ::boost::algorithm::find_format_all_copy( - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - - //! Erase all algorithm ( case insensitive ) - /*! - Remove all the occurrences of the string from the input. - The input sequence is modified in-place. Searching is case insensitive. - - \param Input An input string - \param Search A substring to be searched for. - \param Loc A locale used for case insensitive comparison - */ - template - inline void ierase_all( - SequenceT& Input, - const RangeT& Search, - const std::locale& Loc=std::locale() ) - { - ::boost::algorithm::find_format_all( - Input, - ::boost::algorithm::first_finder(Search, is_iequal(Loc)), - ::boost::algorithm::empty_formatter(Input) ); - } - -// erase_head --------------------------------------------------------------------// - - //! Erase head algorithm - /*! - Remove the head from the input. The head is a prefix of a sequence of given size. - If the sequence is shorter then required, the whole string is - considered to be the head. The result is a modified copy of the input. - It is returned as a sequence or copied to the output iterator. - - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param N Length of the head. - For N>=0, at most N characters are extracted. - For N<0, size(Input)-|N| characters are extracted. - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename RangeT> - inline OutputIteratorT erase_head_copy( - OutputIteratorT Output, - const RangeT& Input, - int N ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::head_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - - //! Erase head algorithm - /*! - \overload - */ - template - inline SequenceT erase_head_copy( - const SequenceT& Input, - int N ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::head_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - - //! Erase head algorithm - /*! - Remove the head from the input. The head is a prefix of a sequence of given size. - If the sequence is shorter then required, the whole string is - considered to be the head. The input sequence is modified in-place. - - \param Input An input string - \param N Length of the head - For N>=0, at most N characters are extracted. - For N<0, size(Input)-|N| characters are extracted. - */ - template - inline void erase_head( - SequenceT& Input, - int N ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::head_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - -// erase_tail --------------------------------------------------------------------// - - //! Erase tail algorithm - /*! - Remove the tail from the input. The tail is a suffix of a sequence of given size. - If the sequence is shorter then required, the whole string is - considered to be the tail. - The result is a modified copy of the input. It is returned as a sequence - or copied to the output iterator. - - \param Output An output iterator to which the result will be copied - \param Input An input string - \param N Length of the tail. - For N>=0, at most N characters are extracted. - For N<0, size(Input)-|N| characters are extracted. - \return An output iterator pointing just after the last inserted character or - a modified copy of the input - - \note The second variant of this function provides the strong exception-safety guarantee - */ - template< - typename OutputIteratorT, - typename RangeT> - inline OutputIteratorT erase_tail_copy( - OutputIteratorT Output, - const RangeT& Input, - int N ) - { - return ::boost::algorithm::find_format_copy( - Output, - Input, - ::boost::algorithm::tail_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - - //! Erase tail algorithm - /*! - \overload - */ - template - inline SequenceT erase_tail_copy( - const SequenceT& Input, - int N ) - { - return ::boost::algorithm::find_format_copy( - Input, - ::boost::algorithm::tail_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - - //! Erase tail algorithm - /*! - Remove the tail from the input. The tail is a suffix of a sequence of given size. - If the sequence is shorter then required, the whole string is - considered to be the tail. The input sequence is modified in-place. - - \param Input An input string - \param N Length of the tail - For N>=0, at most N characters are extracted. - For N<0, size(Input)-|N| characters are extracted. - */ - template - inline void erase_tail( - SequenceT& Input, - int N ) - { - ::boost::algorithm::find_format( - Input, - ::boost::algorithm::tail_finder(N), - ::boost::algorithm::empty_formatter( Input ) ); - } - - } // namespace algorithm - - // pull names into the boost namespace - using algorithm::erase_range_copy; - using algorithm::erase_range; - using algorithm::erase_first_copy; - using algorithm::erase_first; - using algorithm::ierase_first_copy; - using algorithm::ierase_first; - using algorithm::erase_last_copy; - using algorithm::erase_last; - using algorithm::ierase_last_copy; - using algorithm::ierase_last; - using algorithm::erase_nth_copy; - using algorithm::erase_nth; - using algorithm::ierase_nth_copy; - using algorithm::ierase_nth; - using algorithm::erase_all_copy; - using algorithm::erase_all; - using algorithm::ierase_all_copy; - using algorithm::ierase_all; - using algorithm::erase_head_copy; - using algorithm::erase_head; - using algorithm::erase_tail_copy; - using algorithm::erase_tail; - -} // namespace boost - - -#endif // BOOST_ERASE_HPP diff --git a/boost/asio/any_completion_handler.hpp b/boost/asio/any_completion_handler.hpp index ae73387..3164492 100644 --- a/boost/asio/any_completion_handler.hpp +++ b/boost/asio/any_completion_handler.hpp @@ -23,9 +23,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -126,6 +128,13 @@ public: (get_associated_executor)(handler_, candidate)); } + any_completion_executor immediate_executor( + const any_io_executor& candidate) const BOOST_ASIO_NOEXCEPT + { + return any_completion_executor(std::nothrow, + (get_associated_immediate_executor)(handler_, candidate)); + } + void* allocate(std::size_t size, std::size_t align) const { typename std::allocator_traits< @@ -306,6 +315,36 @@ private: type executor_fn_; }; +class any_completion_handler_immediate_executor_fn +{ +public: + using type = any_completion_executor(*)( + any_completion_handler_impl_base*, const any_io_executor&); + + constexpr any_completion_handler_immediate_executor_fn(type fn) + : immediate_executor_fn_(fn) + { + } + + any_completion_executor immediate_executor( + any_completion_handler_impl_base* impl, + const any_io_executor& candidate) const + { + return immediate_executor_fn_(impl, candidate); + } + + template + static any_completion_executor impl(any_completion_handler_impl_base* impl, + const any_io_executor& candidate) + { + return static_cast*>( + impl)->immediate_executor(candidate); + } + +private: + type immediate_executor_fn_; +}; + class any_completion_handler_allocate_fn { public: @@ -368,6 +407,7 @@ template class any_completion_handler_fn_table : private any_completion_handler_destroy_fn, private any_completion_handler_executor_fn, + private any_completion_handler_immediate_executor_fn, private any_completion_handler_allocate_fn, private any_completion_handler_deallocate_fn, private any_completion_handler_call_fns @@ -377,11 +417,13 @@ public: constexpr any_completion_handler_fn_table( any_completion_handler_destroy_fn::type destroy_fn, any_completion_handler_executor_fn::type executor_fn, + any_completion_handler_immediate_executor_fn::type immediate_executor_fn, any_completion_handler_allocate_fn::type allocate_fn, any_completion_handler_deallocate_fn::type deallocate_fn, CallFns... call_fns) : any_completion_handler_destroy_fn(destroy_fn), any_completion_handler_executor_fn(executor_fn), + any_completion_handler_immediate_executor_fn(immediate_executor_fn), any_completion_handler_allocate_fn(allocate_fn), any_completion_handler_deallocate_fn(deallocate_fn), any_completion_handler_call_fns(call_fns...) @@ -390,6 +432,7 @@ public: using any_completion_handler_destroy_fn::destroy; using any_completion_handler_executor_fn::executor; + using any_completion_handler_immediate_executor_fn::immediate_executor; using any_completion_handler_allocate_fn::allocate; using any_completion_handler_deallocate_fn::deallocate; using any_completion_handler_call_fns::call; @@ -402,6 +445,7 @@ struct any_completion_handler_fn_table_instance value = any_completion_handler_fn_table( &any_completion_handler_destroy_fn::impl, &any_completion_handler_executor_fn::impl, + &any_completion_handler_immediate_executor_fn::impl, &any_completion_handler_allocate_fn::impl, &any_completion_handler_deallocate_fn::impl, &any_completion_handler_call_fn::template impl...); @@ -577,6 +621,9 @@ private: template friend struct associated_executor; + template + friend struct associated_immediate_executor; + const detail::any_completion_handler_fn_table* fn_table_; detail::any_completion_handler_impl_base* impl_; #endif // !defined(GENERATING_DOCUMENTATION) @@ -751,6 +798,20 @@ struct associated_executor, Candidate> } }; +template +struct associated_immediate_executor< + any_completion_handler, Candidate> +{ + using type = any_completion_executor; + + static type get(const any_completion_handler& handler, + const Candidate& candidate = Candidate()) BOOST_ASIO_NOEXCEPT + { + return handler.fn_table_->immediate_executor(handler.impl_, + any_io_executor(std::nothrow, candidate)); + } +}; + } // namespace asio } // namespace boost diff --git a/boost/asio/bind_allocator.hpp b/boost/asio/bind_allocator.hpp index 49bb2c7..8123f1f 100644 --- a/boost/asio/bind_allocator.hpp +++ b/boost/asio/bind_allocator.hpp @@ -472,20 +472,40 @@ namespace detail { template -struct allocator_binder_async_result_completion_handler_type +class allocator_binder_completion_handler_async_result { +public: + template + explicit allocator_binder_completion_handler_async_result(T&) + { + } }; template -struct allocator_binder_async_result_completion_handler_type< +class allocator_binder_completion_handler_async_result< TargetAsyncResult, Allocator, typename void_type< typename TargetAsyncResult::completion_handler_type >::type> { +public: typedef allocator_binder< typename TargetAsyncResult::completion_handler_type, Allocator> completion_handler_type; + + explicit allocator_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + typename TargetAsyncResult::return_type get() + { + return target_.get(); + } + +private: + TargetAsyncResult target_; }; template @@ -507,22 +527,18 @@ struct allocator_binder_async_result_return_type< template class async_result, Signature> : - public detail::allocator_binder_async_result_completion_handler_type< + public detail::allocator_binder_completion_handler_async_result< async_result, Allocator>, public detail::allocator_binder_async_result_return_type< async_result > { public: explicit async_result(allocator_binder& b) - : target_(b.get()) + : detail::allocator_binder_completion_handler_async_result< + async_result, Allocator>(b.get()) { } - typename async_result::return_type get() - { - return target_.get(); - } - template struct init_wrapper { diff --git a/boost/asio/bind_cancellation_slot.hpp b/boost/asio/bind_cancellation_slot.hpp index 91e97cf..19f3af8 100644 --- a/boost/asio/bind_cancellation_slot.hpp +++ b/boost/asio/bind_cancellation_slot.hpp @@ -474,20 +474,40 @@ namespace detail { template -struct cancellation_slot_binder_async_result_completion_handler_type +class cancellation_slot_binder_completion_handler_async_result { +public: + template + explicit cancellation_slot_binder_completion_handler_async_result(T&) + { + } }; template -struct cancellation_slot_binder_async_result_completion_handler_type< +class cancellation_slot_binder_completion_handler_async_result< TargetAsyncResult, CancellationSlot, typename void_type< typename TargetAsyncResult::completion_handler_type >::type> { +public: typedef cancellation_slot_binder< typename TargetAsyncResult::completion_handler_type, CancellationSlot> completion_handler_type; + + explicit cancellation_slot_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + typename TargetAsyncResult::return_type get() + { + return target_.get(); + } + +private: + TargetAsyncResult target_; }; template @@ -509,22 +529,18 @@ struct cancellation_slot_binder_async_result_return_type< template class async_result, Signature> : - public detail::cancellation_slot_binder_async_result_completion_handler_type< + public detail::cancellation_slot_binder_completion_handler_async_result< async_result, CancellationSlot>, public detail::cancellation_slot_binder_async_result_return_type< async_result > { public: explicit async_result(cancellation_slot_binder& b) - : target_(b.get()) + : detail::cancellation_slot_binder_completion_handler_async_result< + async_result, CancellationSlot>(b.get()) { } - typename async_result::return_type get() - { - return target_.get(); - } - template struct init_wrapper { diff --git a/boost/asio/bind_immediate_executor.hpp b/boost/asio/bind_immediate_executor.hpp index f9ff922..a798759 100644 --- a/boost/asio/bind_immediate_executor.hpp +++ b/boost/asio/bind_immediate_executor.hpp @@ -472,22 +472,41 @@ bind_immediate_executor(const Executor& e, BOOST_ASIO_MOVE_ARG(T) t) namespace detail { -template -struct immediate_executor_binder_async_result_completion_handler_type +template +class immediate_executor_binder_completion_handler_async_result { +public: + template + explicit immediate_executor_binder_completion_handler_async_result(T&) + { + } }; template -struct immediate_executor_binder_async_result_completion_handler_type< +class immediate_executor_binder_completion_handler_async_result< TargetAsyncResult, Executor, typename void_type< typename TargetAsyncResult::completion_handler_type >::type> { +public: typedef immediate_executor_binder< typename TargetAsyncResult::completion_handler_type, Executor> completion_handler_type; + + explicit immediate_executor_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + typename TargetAsyncResult::return_type get() + { + return target_.get(); + } + +private: + TargetAsyncResult target_; }; template @@ -509,22 +528,18 @@ struct immediate_executor_binder_async_result_return_type< template class async_result, Signature> : - public detail::immediate_executor_binder_async_result_completion_handler_type< + public detail::immediate_executor_binder_completion_handler_async_result< async_result, Executor>, public detail::immediate_executor_binder_async_result_return_type< async_result > { public: explicit async_result(immediate_executor_binder& b) - : target_(b.get()) + : detail::immediate_executor_binder_completion_handler_async_result< + async_result, Executor>(b.get()) { } - typename async_result::return_type get() - { - return target_.get(); - } - template struct init_wrapper { diff --git a/boost/asio/compose.hpp b/boost/asio/compose.hpp index 3a43fbe..5f659ba 100644 --- a/boost/asio/compose.hpp +++ b/boost/asio/compose.hpp @@ -340,6 +340,13 @@ struct associator #endif // defined(BOOST_ASIO_HAS_UNISTD_H) -// Linux: epoll, eventfd and timerfd. +// Linux: epoll, eventfd, timerfd and io_uring. #if defined(__linux__) # include # if !defined(BOOST_ASIO_HAS_EPOLL) @@ -1703,6 +1703,11 @@ # endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) # endif // defined(BOOST_ASIO_HAS_EPOLL) # endif // !defined(BOOST_ASIO_HAS_TIMERFD) +# if defined(BOOST_ASIO_HAS_IO_URING) +# if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) +# error Linux kernel 5.10 or later is required to support io_uring +# endif // LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) +# endif // defined(BOOST_ASIO_HAS_IO_URING) #endif // defined(__linux__) // Linux: io_uring is used instead of epoll. @@ -2042,7 +2047,7 @@ # endif // !defined(BOOST_ASIO_DISABLE_HANDLER_HOOKS) #endif // !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) -// Support for the __thread keyword extension. +// Support for the __thread keyword extension, or equivalent. #if !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) # if defined(__linux__) # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) @@ -2064,6 +2069,22 @@ # define BOOST_ASIO_THREAD_KEYWORD __declspec(thread) # endif // (_MSC_VER >= 1700) # endif // defined(BOOST_ASIO_MSVC) && defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if defined(__APPLE__) +# if defined(__clang__) +# if defined(__apple_build_version__) +# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define BOOST_ASIO_THREAD_KEYWORD __thread +# endif // defined(__apple_build_version__) +# endif // defined(__clang__) +# endif // defined(__APPLE__) +# if !defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) +# if !defined(BOOST_NO_CXX11_THREAD_LOCAL) +# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define BOOST_ASIO_THREAD_KEYWORD thread_local +# endif // !defined(BOOST_NO_CXX11_THREAD_LOCAL) +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) +# endif // !defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION) #endif // !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) #if !defined(BOOST_ASIO_THREAD_KEYWORD) # define BOOST_ASIO_THREAD_KEYWORD __thread diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp index 506b1ae..97a66f0 100644 --- a/boost/asio/detail/dev_poll_reactor.hpp +++ b/boost/asio/detail/dev_poll_reactor.hpp @@ -109,10 +109,9 @@ public: { start_op(op_type, descriptor, descriptor_data, op, is_continuation, allow_speculative, - &epoll_reactor::call_post_immediate_completion, this); + &dev_poll_reactor::call_post_immediate_completion, this); } - // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. diff --git a/boost/asio/detail/impl/io_uring_service.ipp b/boost/asio/detail/impl/io_uring_service.ipp index 98a08a6..f0f4c84 100644 --- a/boost/asio/detail/impl/io_uring_service.ipp +++ b/boost/asio/detail/impl/io_uring_service.ipp @@ -436,15 +436,16 @@ void io_uring_service::run(long usec, op_queue& ops) ? ::io_uring_peek_cqe(&ring_, &cqe) : ::io_uring_wait_cqe(&ring_, &cqe); - if (result == 0 && usec > 0) + if (local_ops > 0) { - if (::io_uring_cqe_get_data(cqe) != &ts) + if (result != 0 || ::io_uring_cqe_get_data(cqe) != &ts) { mutex::scoped_lock lock(mutex_); if (::io_uring_sqe* sqe = get_sqe()) { ++local_ops; ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&ts), 0); + ::io_uring_sqe_set_data(sqe, &ts); submit_sqes(); } } @@ -452,37 +453,41 @@ void io_uring_service::run(long usec, op_queue& ops) bool check_timers = false; int count = 0; - while (result == 0) + while (result == 0 || local_ops > 0) { - if (void* ptr = ::io_uring_cqe_get_data(cqe)) + if (result == 0) { - if (ptr == this) + if (void* ptr = ::io_uring_cqe_get_data(cqe)) { - // The io_uring service was interrupted. - } - else if (ptr == &timer_queues_) - { - check_timers = true; - } - else if (ptr == &timeout_) - { - check_timers = true; - timeout_.tv_sec = 0; - timeout_.tv_nsec = 0; - } - else if (ptr == &ts) - { - --local_ops; - } - else - { - io_queue* io_q = static_cast(ptr); - io_q->set_result(cqe->res); - ops.push(io_q); + if (ptr == this) + { + // The io_uring service was interrupted. + } + else if (ptr == &timer_queues_) + { + check_timers = true; + } + else if (ptr == &timeout_) + { + check_timers = true; + timeout_.tv_sec = 0; + timeout_.tv_nsec = 0; + } + else if (ptr == &ts) + { + --local_ops; + } + else + { + io_queue* io_q = static_cast(ptr); + io_q->set_result(cqe->res); + ops.push(io_q); + } } + ::io_uring_cqe_seen(&ring_, cqe); + ++count; } - ::io_uring_cqe_seen(&ring_, cqe); - result = (++count < complete_batch_size || local_ops > 0) + result = (count < complete_batch_size || local_ops > 0) ? ::io_uring_peek_cqe(&ring_, &cqe) : -EAGAIN; } diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp index 695b688..5719f2a 100644 --- a/boost/asio/detail/impl/signal_set_service.ipp +++ b/boost/asio/detail/impl/signal_set_service.ipp @@ -387,6 +387,7 @@ boost::system::error_code signal_set_service::add( if (state->flags_[signal_number] != signal_set_base::flags::dont_care) { ec = boost::asio::error::invalid_argument; + delete new_registration; return ec; } struct sigaction sa; @@ -398,6 +399,7 @@ boost::system::error_code signal_set_service::add( { ec = boost::system::error_code(errno, boost::asio::error::get_system_category()); + delete new_registration; return ec; } state->flags_[signal_number] = f; diff --git a/boost/asio/detail/memory.hpp b/boost/asio/detail/memory.hpp index 5aec12f..24de6ff 100644 --- a/boost/asio/detail/memory.hpp +++ b/boost/asio/detail/memory.hpp @@ -46,10 +46,12 @@ namespace asio { namespace detail { #if defined(BOOST_ASIO_HAS_STD_SHARED_PTR) +using std::allocate_shared; using std::make_shared; using std::shared_ptr; using std::weak_ptr; #else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR) +using boost::allocate_shared; using boost::make_shared; using boost::shared_ptr; using boost::weak_ptr; diff --git a/boost/asio/detail/reactive_socket_service_base.hpp b/boost/asio/detail/reactive_socket_service_base.hpp index 6dc7648..0c44448 100644 --- a/boost/asio/detail/reactive_socket_service_base.hpp +++ b/boost/asio/detail/reactive_socket_service_base.hpp @@ -701,7 +701,7 @@ protected: { public: reactor_op_cancellation(reactor* r, - reactor::per_descriptor_data* p, int d, int o) + reactor::per_descriptor_data* p, socket_type d, int o) : reactor_(r), reactor_data_(p), descriptor_(d), @@ -724,7 +724,7 @@ protected: private: reactor* reactor_; reactor::per_descriptor_data* reactor_data_; - int descriptor_; + socket_type descriptor_; int op_type_; }; diff --git a/boost/asio/execution/any_executor.hpp b/boost/asio/execution/any_executor.hpp index 2514e4c..c3293bd 100644 --- a/boost/asio/execution/any_executor.hpp +++ b/boost/asio/execution/any_executor.hpp @@ -1824,6 +1824,11 @@ public: >::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_property found; prop_fns_[found::index].query(0, object_fns_->target(*this), &static_cast(p)); @@ -1843,6 +1848,11 @@ public: >::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_property found; typename remove_reference< typename found::query_result_type>::type* result = 0; @@ -1865,6 +1875,11 @@ public: >::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_property found; typename found::query_result_type result; prop_fns_[found::index].query(&result, object_fns_->target(*this), @@ -1890,6 +1905,11 @@ public: >::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_property found; typename found::query_result_type* result; prop_fns_[found::index].query(&result, object_fns_->target(*this), @@ -1910,6 +1930,11 @@ public: find_convertible_requirable_property::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_requirable_property found; return prop_fns_[found::index].require(object_fns_->target(*this), &static_cast(p)); @@ -1927,6 +1952,11 @@ public: find_convertible_preferable_property::value >::type* = 0) const { + if (!target_) + { + bad_executor ex; + boost::asio::detail::throw_exception(ex); + } typedef find_convertible_preferable_property found; return prop_fns_[found::index].prefer(object_fns_->target(*this), &static_cast(p)); @@ -2307,6 +2337,11 @@ inline void swap(any_executor& a, >::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_property found; \ prop_fns_[found::index].query(0, object_fns_->target(*this), \ &static_cast(p)); \ @@ -2326,6 +2361,11 @@ inline void swap(any_executor& a, >::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_property found; \ typename remove_reference< \ typename found::query_result_type>::type* result; \ @@ -2348,6 +2388,11 @@ inline void swap(any_executor& a, >::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_property found; \ typename found::query_result_type result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ @@ -2373,6 +2418,11 @@ inline void swap(any_executor& a, >::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_property found; \ typename found::query_result_type* result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ @@ -2393,6 +2443,11 @@ inline void swap(any_executor& a, find_convertible_requirable_property::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_requirable_property found; \ return prop_fns_[found::index].require(object_fns_->target(*this), \ &static_cast(p)); \ @@ -2410,6 +2465,11 @@ inline void swap(any_executor& a, find_convertible_preferable_property::value \ >::type* = 0) const \ { \ + if (!target_) \ + { \ + bad_executor ex; \ + boost::asio::detail::throw_exception(ex); \ + } \ typedef find_convertible_preferable_property found; \ return prop_fns_[found::index].prefer(object_fns_->target(*this), \ &static_cast(p)); \ diff --git a/boost/asio/impl/co_spawn.hpp b/boost/asio/impl/co_spawn.hpp index c6d75ea..974d5ff 100644 --- a/boost/asio/impl/co_spawn.hpp +++ b/boost/asio/impl/co_spawn.hpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -70,43 +72,90 @@ struct co_spawn_work_guard -inline co_spawn_work_guard -make_co_spawn_work_guard(const Executor& ex) +template +struct co_spawn_state { - return co_spawn_work_guard(ex); -} + template + co_spawn_state(H&& h, const Executor& ex, F&& f) + : handler(std::forward(h)), + spawn_work(ex), + handler_work(boost::asio::get_associated_executor(handler, ex)), + function(std::forward(f)) + { + } -template + Handler handler; + co_spawn_work_guard spawn_work; + co_spawn_work_guard::type> handler_work; + Function function; +}; + +template +struct co_spawn_state::asio_associated_executor_is_unspecialised, + void + >::value + >::type> +{ + template + co_spawn_state(H&& h, const Executor& ex, F&& f) + : handler(std::forward(h)), + handler_work(ex), + function(std::forward(f)) + { + } + + Handler handler; + co_spawn_work_guard handler_work; + Function function; +}; + +struct co_spawn_dispatch +{ + template + auto operator()(CompletionToken&& token) const + -> decltype(boost::asio::dispatch(std::forward(token))) + { + return boost::asio::dispatch(std::forward(token)); + } +}; + +struct co_spawn_post +{ + template + auto operator()(CompletionToken&& token) const + -> decltype(boost::asio::post(std::forward(token))) + { + return boost::asio::post(std::forward(token)); + } +}; + +template awaitable co_spawn_entry_point( - awaitable*, Executor ex, F f, Handler handler) + awaitable*, co_spawn_state s) { - auto spawn_work = make_co_spawn_work_guard(ex); - auto handler_work = make_co_spawn_work_guard( - boost::asio::get_associated_executor(handler, ex)); - - (void) co_await (dispatch)( - use_awaitable_t{__FILE__, __LINE__, "co_spawn_entry_point"}); + (void) co_await co_spawn_dispatch{}; (co_await awaitable_thread_has_context_switched{}) = false; std::exception_ptr e = nullptr; bool done = false; try { - T t = co_await f(); + T t = co_await s.function(); done = true; bool switched = (co_await awaitable_thread_has_context_switched{}); if (!switched) - { - (void) co_await (post)( - use_awaitable_t{__FILE__, - __LINE__, "co_spawn_entry_point"}); - } + (void) co_await co_spawn_post(); - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), t = std::move(t)]() mutable + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), t = std::move(t)]() mutable { std::move(handler)(std::exception_ptr(), std::move(t)); }); @@ -123,34 +172,26 @@ awaitable co_spawn_entry_point( bool switched = (co_await awaitable_thread_has_context_switched{}); if (!switched) - { - (void) co_await (post)( - use_awaitable_t{__FILE__, __LINE__, "co_spawn_entry_point"}); - } + (void) co_await co_spawn_post(); - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), e]() mutable { std::move(handler)(e, T()); }); } -template +template awaitable co_spawn_entry_point( - awaitable*, Executor ex, F f, Handler handler) + awaitable*, co_spawn_state s) { - auto spawn_work = make_co_spawn_work_guard(ex); - auto handler_work = make_co_spawn_work_guard( - boost::asio::get_associated_executor(handler, ex)); - - (void) co_await (dispatch)( - use_awaitable_t{__FILE__, __LINE__, "co_spawn_entry_point"}); + (void) co_await co_spawn_dispatch{}; (co_await awaitable_thread_has_context_switched{}) = false; std::exception_ptr e = nullptr; try { - co_await f(); + co_await s.function(); } catch (...) { @@ -159,13 +200,10 @@ awaitable co_spawn_entry_point( bool switched = (co_await awaitable_thread_has_context_switched{}); if (!switched) - { - (void) co_await (post)( - use_awaitable_t{__FILE__, __LINE__, "co_spawn_entry_point"}); - } + (void) co_await co_spawn_post(); - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), e]() mutable { std::move(handler)(e); }); @@ -194,27 +232,29 @@ class co_spawn_cancellation_handler { public: co_spawn_cancellation_handler(const Handler&, const Executor& ex) - : ex_(ex) + : signal_(detail::allocate_shared( + detail::recycling_allocator())), + ex_(ex) { } cancellation_slot slot() { - return signal_.slot(); + return signal_->slot(); } void operator()(cancellation_type_t type) { - cancellation_signal* sig = &signal_; + shared_ptr sig = signal_; boost::asio::dispatch(ex_, [sig, type]{ sig->emit(type); }); } private: - cancellation_signal signal_; + shared_ptr signal_; Executor ex_; }; - template class co_spawn_cancellation_handler::type awaitable_type; typedef typename decay::type handler_type; + typedef typename decay::type function_type; typedef co_spawn_cancellation_handler< handler_type, Executor> cancel_handler_type; @@ -282,7 +323,8 @@ public: cancellation_state cancel_state(proxy_slot); auto a = (co_spawn_entry_point)(static_cast(nullptr), - ex_, std::forward(f), std::forward(handler)); + co_spawn_state( + std::forward(handler), ex_, std::forward(f))); awaitable_handler(std::move(a), ex_, proxy_slot, cancel_state).launch(); } diff --git a/boost/asio/ip/bad_address_cast.hpp b/boost/asio/ip/bad_address_cast.hpp index 28a1786..bd6c39f 100644 --- a/boost/asio/ip/bad_address_cast.hpp +++ b/boost/asio/ip/bad_address_cast.hpp @@ -36,6 +36,16 @@ public: /// Default constructor. bad_address_cast() {} + /// Copy constructor. + bad_address_cast(const bad_address_cast& other) BOOST_ASIO_NOEXCEPT_OR_NOTHROW +#if defined(BOOST_ASIO_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS + : std::exception(static_cast(other)) +#else + : std::bad_cast(static_cast(other)) +#endif + { + } + /// Destructor. virtual ~bad_address_cast() BOOST_ASIO_NOEXCEPT_OR_NOTHROW {} diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp index 53e4fd4..b548149 100644 --- a/boost/asio/version.hpp +++ b/boost/asio/version.hpp @@ -18,6 +18,6 @@ // BOOST_ASIO_VERSION % 100 is the sub-minor version // BOOST_ASIO_VERSION / 100 % 1000 is the minor version // BOOST_ASIO_VERSION / 100000 is the major version -#define BOOST_ASIO_VERSION 102800 // 1.28.0 +#define BOOST_ASIO_VERSION 102802 // 1.28.2 #endif // BOOST_ASIO_VERSION_HPP diff --git a/boost/assert/source_location.hpp b/boost/assert/source_location.hpp index 0d76858..09770f7 100644 --- a/boost/assert/source_location.hpp +++ b/boost/assert/source_location.hpp @@ -161,7 +161,10 @@ template std::basic_ostream & operator<<( std::basic_ost # define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, BOOST_CURRENT_LOCATION_IMPL_1(__LINE__), "") -#elif defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L +#elif defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L && !defined(__NVCC__) + +// Under nvcc, __builtin_source_location is not constexpr +// https://github.com/boostorg/assert/issues/32 # define BOOST_CURRENT_LOCATION ::boost::source_location(::std::source_location::current()) diff --git a/boost/atomic/atomic_ref.hpp b/boost/atomic/atomic_ref.hpp new file mode 100644 index 0000000..dc388f0 --- /dev/null +++ b/boost/atomic/atomic_ref.hpp @@ -0,0 +1,98 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020-2021 Andrey Semashev + */ +/*! + * \file atomic/atomic_ref.hpp + * + * This header contains definition of \c atomic_ref template. + */ + +#ifndef BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_ +#define BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { + +//! Atomic reference to external object +template< typename T > +class atomic_ref : + public atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type, false > +{ +private: + typedef atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type, false > base_type; + typedef typename base_type::value_arg_type value_arg_type; + +public: + typedef typename base_type::value_type value_type; + + BOOST_STATIC_ASSERT_MSG(sizeof(value_type) > 0u, "boost::atomic_ref requires T to be a complete type"); +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE) + BOOST_STATIC_ASSERT_MSG(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic_ref requires T to be a trivially copyable type"); +#endif + +private: + typedef typename base_type::storage_type storage_type; + +public: + BOOST_DEFAULTED_FUNCTION(atomic_ref(atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + // Check that referenced object alignment satisfies required alignment + BOOST_ASSERT((((atomics::detail::uintptr_t)this->m_value) & (base_type::required_alignment - 1u)) == 0u); + } + + BOOST_FORCEINLINE value_type operator= (value_arg_type v) const BOOST_NOEXCEPT + { + this->store(v); + return v; + } + + BOOST_FORCEINLINE operator value_type() const BOOST_NOEXCEPT + { + return this->load(); + } + + BOOST_DELETED_FUNCTION(atomic_ref& operator= (atomic_ref const&)) +}; + +#if !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES) +template< typename T > +atomic_ref(T&) -> atomic_ref< T >; +#endif // !defined(BOOST_NO_CXX17_DEDUCTION_GUIDES) + +//! Atomic reference factory function +template< typename T > +BOOST_FORCEINLINE atomic_ref< T > make_atomic_ref(T& value) BOOST_NOEXCEPT +{ + return atomic_ref< T >(value); +} + +} // namespace atomics + +using atomics::atomic_ref; +using atomics::make_atomic_ref; + +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_ATOMIC_REF_HPP_INCLUDED_ diff --git a/boost/atomic/capabilities.hpp b/boost/atomic/capabilities.hpp new file mode 100644 index 0000000..a17bde4 --- /dev/null +++ b/boost/atomic/capabilities.hpp @@ -0,0 +1,21 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/capabilities.hpp + * + * This header defines feature capabilities macros. + */ + +#ifndef BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_ +#define BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_ + +#include +#include +#include + +#endif // BOOST_ATOMIC_CAPABILITIES_HPP_INCLUDED_ diff --git a/boost/atomic/detail/addressof.hpp b/boost/atomic/detail/addressof.hpp new file mode 100644 index 0000000..0bb551b --- /dev/null +++ b/boost/atomic/detail/addressof.hpp @@ -0,0 +1,65 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/addressof.hpp + * + * This header defines \c addressof helper function. It is similar to \c boost::addressof but it is more + * lightweight and also contains a workaround for some compiler warnings. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Detection logic is based on boost/core/addressof.hpp +#if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215 +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF +#elif defined(BOOST_GCC) && BOOST_GCC >= 70000 +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF +#elif defined(__has_builtin) +#if __has_builtin(__builtin_addressof) +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF +#endif +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T > +BOOST_FORCEINLINE +#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF) +BOOST_CONSTEXPR +#endif +T* addressof(T& value) BOOST_NOEXCEPT +{ +#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF) + return __builtin_addressof(value); +#else + // Note: The point of using a local struct as the intermediate type instead of char is to avoid gcc warnings + // if T is a const volatile char*: + // warning: casting 'const volatile char* const' to 'const volatile char&' does not dereference pointer + // The local struct makes sure T is not related to the cast target type. + struct opaque_type; + return reinterpret_cast< T* >(&const_cast< opaque_type& >(reinterpret_cast< const volatile opaque_type& >(value))); +#endif +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ADDRESSOF_HPP_INCLUDED_ diff --git a/boost/atomic/detail/aligned_variable.hpp b/boost/atomic/detail/aligned_variable.hpp new file mode 100644 index 0000000..feae43c --- /dev/null +++ b/boost/atomic/detail/aligned_variable.hpp @@ -0,0 +1,57 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/aligned_variable.hpp + * + * This header defines a convenience macro for declaring aligned variables + */ + +#ifndef BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_ + +#include +#if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS) +#include +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS) + +#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR(var_alignment, var_type, var_name) \ + alignas(var_alignment) var_type var_name + +#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(var_alignment, var_type, var_name) \ + alignas(var_alignment) var_type var_name + +#else // !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS) + +// Note: Some compilers cannot use constant expressions in alignment attributes or alignas, so we have to use the union trick +#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR(var_alignment, var_type, var_name) \ + union \ + { \ + var_type var_name; \ + boost::type_with_alignment< var_alignment >::type BOOST_JOIN(var_name, _aligner); \ + } + +#define BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(var_alignment, var_type, var_name) \ + union \ + { \ + var_type var_name; \ + typename boost::type_with_alignment< var_alignment >::type BOOST_JOIN(var_name, _aligner); \ + } + +#endif // !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS) + +#include + +#endif // BOOST_ATOMIC_DETAIL_ALIGNED_VARIABLE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/atomic_flag_impl.hpp b/boost/atomic/detail/atomic_flag_impl.hpp new file mode 100644 index 0000000..a79d4ad --- /dev/null +++ b/boost/atomic/detail/atomic_flag_impl.hpp @@ -0,0 +1,129 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/atomic_flag_impl.hpp + * + * This header contains implementation of \c atomic_flag. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +/* + * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, + * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. + */ + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT) || defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) +#define BOOST_ATOMIC_NO_ATOMIC_FLAG_INIT +#else +#define BOOST_ATOMIC_FLAG_INIT {} +#endif + +//! Atomic flag implementation +template< bool IsInterprocess > +struct atomic_flag_impl +{ + // Prefer 4-byte storage as most platforms support waiting/notifying operations without a lock pool for 32-bit integers + typedef atomics::detail::core_operations< 4u, false, IsInterprocess > core_operations; + typedef atomics::detail::wait_operations< core_operations > wait_operations; + typedef typename core_operations::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free; + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify; + + BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(core_operations::storage_alignment, storage_type, m_storage); + + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT atomic_flag_impl() BOOST_NOEXCEPT : m_storage(0u) + { + } + + BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT + { + return is_always_lock_free; + } + + BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT + { + return wait_operations::has_native_wait_notify(m_storage); + } + + BOOST_FORCEINLINE bool test(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + return !!core_operations::load(m_storage, order); + } + + BOOST_FORCEINLINE bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return core_operations::test_and_set(m_storage, order); + } + + BOOST_FORCEINLINE void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + core_operations::clear(m_storage, order); + } + + BOOST_FORCEINLINE bool wait(bool old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return !!wait_operations::wait(m_storage, static_cast< storage_type >(old_val), order); + } + + BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT + { + wait_operations::notify_one(m_storage); + } + + BOOST_FORCEINLINE void notify_all() volatile BOOST_NOEXCEPT + { + wait_operations::notify_all(m_storage); + } + + BOOST_DELETED_FUNCTION(atomic_flag_impl(atomic_flag_impl const&)) + BOOST_DELETED_FUNCTION(atomic_flag_impl& operator= (atomic_flag_impl const&)) +}; + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template< bool IsInterprocess > +BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::is_always_lock_free; +template< bool IsInterprocess > +BOOST_CONSTEXPR_OR_CONST bool atomic_flag_impl< IsInterprocess >::always_has_native_wait_notify; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_IMPL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/atomic_impl.hpp b/boost/atomic/detail/atomic_impl.hpp new file mode 100644 index 0000000..0fd601b --- /dev/null +++ b/boost/atomic/detail/atomic_impl.hpp @@ -0,0 +1,1265 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014-2020 Andrey Semashev + */ +/*! + * \file atomic/detail/atomic_impl.hpp + * + * This header contains implementation of \c atomic template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_IMPL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ATOMIC_IMPL_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) +#include +#include +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT) && !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST) +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR BOOST_CONSTEXPR +#else +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR +#endif + +/* + * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, + * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. + */ + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T, bool Signed, bool Interprocess > +class base_atomic_common +{ +public: + typedef T value_type; + +protected: + typedef atomics::detail::core_operations< storage_size_of< value_type >::value, Signed, Interprocess > core_operations; + typedef atomics::detail::wait_operations< core_operations > wait_operations; + typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; + typedef typename core_operations::storage_type storage_type; + +protected: + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment ? core_operations::storage_alignment : atomics::detail::alignment_of< value_type >::value; + +public: + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free; + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify; + +protected: + BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(storage_alignment, storage_type, m_storage); + +public: + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT base_atomic_common() BOOST_NOEXCEPT : m_storage() + { + } + + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic_common(storage_type v) BOOST_NOEXCEPT : m_storage(v) + { + } + + BOOST_FORCEINLINE value_type& value() BOOST_NOEXCEPT { return *reinterpret_cast< value_type* >(&m_storage); } + BOOST_FORCEINLINE value_type volatile& value() volatile BOOST_NOEXCEPT { return *reinterpret_cast< volatile value_type* >(&m_storage); } + BOOST_FORCEINLINE value_type const& value() const BOOST_NOEXCEPT { return *reinterpret_cast< const value_type* >(&m_storage); } + BOOST_FORCEINLINE value_type const volatile& value() const volatile BOOST_NOEXCEPT { return *reinterpret_cast< const volatile value_type* >(&m_storage); } + +protected: + BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return m_storage; } + BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return m_storage; } + BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return m_storage; } + BOOST_FORCEINLINE storage_type const volatile& storage() const volatile BOOST_NOEXCEPT { return m_storage; } + +public: + BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT + { + // C++17 requires all instances of atomic<> return a value consistent with is_always_lock_free here. + // Boost.Atomic also enforces the required alignment of the atomic storage, so we can always return is_always_lock_free. + return is_always_lock_free; + } + + BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT + { + return wait_operations::has_native_wait_notify(this->storage()); + } + + BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT + { + wait_operations::notify_one(this->storage()); + } + + BOOST_FORCEINLINE void notify_all() volatile BOOST_NOEXCEPT + { + wait_operations::notify_all(this->storage()); + } +}; + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template< typename T, bool Signed, bool Interprocess > +BOOST_CONSTEXPR_OR_CONST bool base_atomic_common< T, Signed, Interprocess >::is_always_lock_free; +template< typename T, bool Signed, bool Interprocess > +BOOST_CONSTEXPR_OR_CONST bool base_atomic_common< T, Signed, Interprocess >::always_has_native_wait_notify; +#endif + + +template< typename T, bool Interprocess, bool IsTriviallyDefaultConstructible = atomics::detail::is_trivially_default_constructible< T >::value > +class base_atomic_generic; + +template< typename T, bool Interprocess > +class base_atomic_generic< T, Interprocess, true > : + public base_atomic_common< T, false, Interprocess > +{ +private: + typedef base_atomic_common< T, false, Interprocess > base_type; + +protected: + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_generic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR explicit base_atomic_generic(value_arg_type v) BOOST_NOEXCEPT : + base_type(atomics::detail::bitwise_cast< storage_type >(v)) + { + } +}; + +template< typename T, bool Interprocess > +class base_atomic_generic< T, Interprocess, false > : + public base_atomic_common< T, false, Interprocess > +{ +private: + typedef base_atomic_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +public: + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR explicit base_atomic_generic(value_arg_type v = value_type()) BOOST_NOEXCEPT : + base_type(atomics::detail::bitwise_cast< storage_type >(v)) + { + } +}; + + +template< typename T, typename Kind, bool Interprocess > +class base_atomic; + +//! General template. Implementation for user-defined types, such as structs, and pointers to non-object types +template< typename T, bool Interprocess > +class base_atomic< T, void, Interprocess > : + public base_atomic_generic< T, Interprocess > +{ +private: + typedef base_atomic_generic< T, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR base_atomic() BOOST_NOEXCEPT_IF(atomics::detail::is_nothrow_default_constructible< value_type >::value) : base_type() + { + } + + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + + +//! Implementation for enums +template< typename T, bool Interprocess > +class base_atomic< T, const int, Interprocess > : + public base_atomic_common< T, false, Interprocess > +{ +private: + typedef base_atomic_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(static_cast< storage_type >(v)) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + + +//! Implementation for integers +template< typename T, bool Interprocess > +class base_atomic< T, int, Interprocess > : + public base_atomic_common< T, atomics::detail::is_signed< T >::value, Interprocess > +{ +private: + typedef base_atomic_common< T, atomics::detail::is_signed< T >::value, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef value_type difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(static_cast< storage_type >(v)) {} + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::integral_truncate< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::fetch_and(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::fetch_or(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(core_operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_negate(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_complement(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::negate(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_complement(this->storage(), order)); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_negate(this->storage(), order); + } + + BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_complement(this->storage(), order); + } + + BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::negate_and_test(this->storage(), order); + } + + BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::complement_and_test(this->storage(), order); + } + + BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_set(this->storage(), bit_number, order); + } + + BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_reset(this->storage(), bit_number, order); + } + + BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_complement(this->storage(), bit_number, order); + } + + // Operators + BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT + { + return fetch_add(1); + } + + BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT + { + return add(1); + } + + BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT + { + return sub(1); + } + + BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type operator&=(value_type v) volatile BOOST_NOEXCEPT + { + return bitwise_and(v); + } + + BOOST_FORCEINLINE value_type operator|=(value_type v) volatile BOOST_NOEXCEPT + { + return bitwise_or(v); + } + + BOOST_FORCEINLINE value_type operator^=(value_type v) volatile BOOST_NOEXCEPT + { + return bitwise_xor(v); + } + + BOOST_FORCEINLINE value_type wait(value_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::integral_truncate< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::integral_truncate< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::integral_truncate< value_type >(old_value); + return res; + } +}; + +//! Implementation for bool +template< bool Interprocess > +class base_atomic< bool, int, Interprocess > : + public base_atomic_common< bool, false, Interprocess > +{ +private: + typedef base_atomic_common< bool, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(static_cast< storage_type >(v)) {} + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return !!core_operations::load(this->storage(), order); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return !!core_operations::exchange(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return !!wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = !!old_value; + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = !!old_value; + return res; + } +}; + + +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +//! Implementation for floating point types +template< typename T, bool Interprocess > +class base_atomic< T, float, Interprocess > : + public base_atomic_common< T, false, Interprocess > +{ +private: + typedef base_atomic_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef value_type difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef atomics::detail::fp_operations< extra_operations, value_type > fp_operations; + typedef atomics::detail::extra_fp_operations< fp_operations > extra_fp_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, + atomics::detail::value_size_of< value_type >::value != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment + > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : + base_type(atomics::detail::bitwise_fp_cast< storage_type >(v)) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_fp_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return fp_operations::fetch_add(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return fp_operations::fetch_sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_fp_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_fp_operations::fetch_negate(this->storage(), order); + } + + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_fp_operations::add(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_fp_operations::sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_fp_operations::negate(this->storage(), order); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_fp_operations::opaque_add(this->storage(), v, order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_fp_operations::opaque_sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_fp_operations::opaque_negate(this->storage(), order); + } + + // Operators + BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_fp_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); + return res; + } +}; + +#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + + +//! Implementation for pointers to object types +template< typename T, bool Interprocess > +class base_atomic< T*, void*, Interprocess > : + public base_atomic_common< T*, false, Interprocess > +{ +private: + typedef base_atomic_common< T*, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef std::ptrdiff_t difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + + // uintptr_storage_type is the minimal storage type that is enough to store pointers. The actual storage_type theoretically may be larger, + // if the target architecture only supports atomic ops on larger data. Typically, though, they are the same type. + typedef atomics::detail::uintptr_t uintptr_storage_type; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_ATOMIC_CTOR explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : + base_type(atomics::detail::bitwise_cast< uintptr_storage_type >(v)) + { + } + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::load(this->storage(), order))); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::fetch_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order))); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::fetch_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order))); + } + + BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order))); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order))); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order))); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + extra_operations::opaque_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::add_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return extra_operations::sub_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); + } + + // Operators + BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT + { + return fetch_add(1); + } + + BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT + { + return add(1); + } + + BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT + { + return sub(1); + } + + BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(old_val), order))); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value)); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value)); + return res; + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ATOMIC_IMPl_HPP_INCLUDED_ diff --git a/boost/atomic/detail/atomic_ref_impl.hpp b/boost/atomic/detail/atomic_ref_impl.hpp new file mode 100644 index 0000000..086bdc1 --- /dev/null +++ b/boost/atomic/detail/atomic_ref_impl.hpp @@ -0,0 +1,1228 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/atomic_ref_impl.hpp + * + * This header contains implementation of \c atomic_ref template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) +#include +#include +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +/* + * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, + * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. + */ + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T, bool Signed, bool Interprocess > +struct is_atomic_ref_lock_free +{ + typedef T value_type; + typedef atomics::detail::core_operations< sizeof(value_type), Signed, Interprocess > core_operations; + typedef typename core_operations::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool value = sizeof(value_type) == sizeof(storage_type) && core_operations::is_always_lock_free; +}; + +template< typename T, bool Signed, bool Interprocess > +class base_atomic_ref_common +{ +public: + typedef T value_type; + +protected: + typedef typename atomics::detail::remove_cv< value_type >::type unqualified_value_type; + typedef typename atomics::detail::conditional< + atomics::detail::is_atomic_ref_lock_free< T, Signed, Interprocess >::value, + atomics::detail::core_operations< sizeof(value_type), Signed, Interprocess >, + atomics::detail::core_operations_emulated< sizeof(value_type), atomics::detail::alignment_of< value_type >::value, Signed, Interprocess > + >::type core_operations; + typedef atomics::detail::wait_operations< core_operations > wait_operations; + typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; + typedef typename core_operations::storage_type storage_type; + BOOST_STATIC_ASSERT_MSG(sizeof(storage_type) == sizeof(value_type), "Boost.Atomic internal error: atomic_ref storage size doesn't match the value size"); + +public: + static BOOST_CONSTEXPR_OR_CONST std::size_t required_alignment = atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment ? core_operations::storage_alignment : atomics::detail::alignment_of< value_type >::value; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free; + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify; + +protected: + value_type* m_value; + +public: + BOOST_FORCEINLINE explicit base_atomic_ref_common(value_type& v) BOOST_NOEXCEPT : m_value(atomics::detail::addressof(v)) + { + BOOST_ATOMIC_DETAIL_CLEAR_PADDING(const_cast< unqualified_value_type* >(m_value)); + } + + BOOST_FORCEINLINE value_type& value() const BOOST_NOEXCEPT { return *m_value; } + +protected: + BOOST_FORCEINLINE storage_type& storage() const BOOST_NOEXCEPT + { + return *reinterpret_cast< storage_type* >(const_cast< unqualified_value_type* >(m_value)); + } + +public: + BOOST_FORCEINLINE bool is_lock_free() const BOOST_NOEXCEPT + { + // C++20 specifies that is_lock_free returns true if operations on *all* objects of the atomic_ref type are lock-free. + // This does not allow to return true or false depending on the referenced object runtime alignment. Currently, Boost.Atomic + // follows this specification, although we may support runtime alignment checking in the future. + return is_always_lock_free; + } + + BOOST_FORCEINLINE bool has_native_wait_notify() const BOOST_NOEXCEPT + { + return wait_operations::has_native_wait_notify(this->storage()); + } + + BOOST_FORCEINLINE void notify_one() const BOOST_NOEXCEPT + { + wait_operations::notify_one(this->storage()); + } + + BOOST_FORCEINLINE void notify_all() const BOOST_NOEXCEPT + { + wait_operations::notify_all(this->storage()); + } +}; + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template< typename T, bool Signed, bool Interprocess > +BOOST_CONSTEXPR_OR_CONST std::size_t base_atomic_ref_common< T, Signed, Interprocess >::required_alignment; +template< typename T, bool Signed, bool Interprocess > +BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, Signed, Interprocess >::is_always_lock_free; +template< typename T, bool Signed, bool Interprocess > +BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, Signed, Interprocess >::always_has_native_wait_notify; +#endif + + +template< typename T, typename Kind, bool Interprocess > +class base_atomic_ref; + +//! General template. Implementation for user-defined types, such as structs, and pointers to non-object types +template< typename T, bool Interprocess > +class base_atomic_ref< T, void, Interprocess > : + public base_atomic_ref_common< T, false, Interprocess > +{ +private: + typedef base_atomic_ref_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + + +//! Implementation for enums +template< typename T, bool Interprocess > +class base_atomic_ref< T, const int, Interprocess > : + public base_atomic_ref_common< T, false, Interprocess > +{ +private: + typedef base_atomic_ref_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::value_arg_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + + +//! Implementation for integers +template< typename T, bool Interprocess > +class base_atomic_ref< T, int, Interprocess > : + public base_atomic_ref_common< T, atomics::detail::is_signed< T >::value, Interprocess > +{ +private: + typedef base_atomic_ref_common< T, atomics::detail::is_signed< T >::value, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef typename base_type::value_type difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + } + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_and(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_or(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::fetch_negate(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::fetch_complement(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::negate(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_complement(this->storage(), order)); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_negate(this->storage(), order); + } + + BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_complement(this->storage(), order); + } + + BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::negate_and_test(this->storage(), order); + } + + BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::complement_and_test(this->storage(), order); + } + + BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_set(this->storage(), bit_number, order); + } + + BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_reset(this->storage(), bit_number, order); + } + + BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); + return extra_operations::bit_test_and_complement(this->storage(), bit_number, order); + } + + // Operators + BOOST_FORCEINLINE value_type operator++(int) const BOOST_NOEXCEPT + { + return fetch_add(1); + } + + BOOST_FORCEINLINE value_type operator++() const BOOST_NOEXCEPT + { + return add(1); + } + + BOOST_FORCEINLINE value_type operator--(int) const BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + BOOST_FORCEINLINE value_type operator--() const BOOST_NOEXCEPT + { + return sub(1); + } + + BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type operator&=(value_type v) const BOOST_NOEXCEPT + { + return bitwise_and(v); + } + + BOOST_FORCEINLINE value_type operator|=(value_type v) const BOOST_NOEXCEPT + { + return bitwise_or(v); + } + + BOOST_FORCEINLINE value_type operator^=(value_type v) const BOOST_NOEXCEPT + { + return bitwise_xor(v); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + +//! Implementation for bool +template< bool Interprocess > +class base_atomic_ref< bool, int, Interprocess > : + public base_atomic_ref_common< bool, false, Interprocess > +{ +private: + typedef base_atomic_ref_common< bool, false, Interprocess > base_type; + +public: + typedef bool value_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + } + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return !!core_operations::load(this->storage(), order); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return !!core_operations::exchange(this->storage(), static_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return !!wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = !!old_value; + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = !!old_value; + return res; + } +}; + + +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +//! Implementation for floating point types +template< typename T, bool Interprocess > +class base_atomic_ref< T, float, Interprocess > : + public base_atomic_ref_common< T, false, Interprocess > +{ +private: + typedef base_atomic_ref_common< T, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef typename base_type::value_type difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef atomics::detail::fp_operations< extra_operations, value_type > fp_operations; + typedef atomics::detail::extra_fp_operations< fp_operations > extra_fp_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::integral_constant< bool, atomics::detail::value_size_of< value_type >::value != sizeof(storage_type) > has_padding_bits; +#endif +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, has_padding_bits::value || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + // We only need to call clear_padding_bits if the compiler does not implement + // BOOST_ATOMIC_DETAIL_CLEAR_PADDING, which is called in the base class constructor. +#if defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + this->clear_padding_bits(has_padding_bits()); +#endif // defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + } + + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_fp_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return fp_operations::fetch_add(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return fp_operations::fetch_sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_fp_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_fp_operations::fetch_negate(this->storage(), order); + } + + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_fp_operations::add(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_fp_operations::sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_fp_operations::negate(this->storage(), order); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_fp_operations::opaque_add(this->storage(), v, order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_fp_operations::opaque_sub(this->storage(), v, order); + } + + BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_fp_operations::opaque_negate(this->storage(), order); + } + + // Operators + BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_fp_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: +#if defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::false_type) const BOOST_NOEXCEPT + { + } + + BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::true_type) const BOOST_NOEXCEPT + { + atomics::detail::clear_tail_padding_bits< atomics::detail::value_size_of< value_type >::value >(this->storage()); + } +#endif // defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); + return res; + } +}; + +#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + + +//! Implementation for pointers to object types +template< typename T, bool Interprocess > +class base_atomic_ref< T*, void*, Interprocess > : + public base_atomic_ref_common< T*, false, Interprocess > +{ +private: + typedef base_atomic_ref_common< T*, false, Interprocess > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef std::ptrdiff_t difference_type; + +protected: + typedef typename base_type::core_operations core_operations; + typedef typename base_type::wait_operations wait_operations; + typedef atomics::detail::extra_operations< core_operations > extra_operations; + typedef typename base_type::storage_type storage_type; + typedef value_type value_arg_type; + +private: +#if !defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) || !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + typedef atomics::detail::true_type cxchg_use_bitwise_cast; +#else + typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > cxchg_use_bitwise_cast; +#endif + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) + BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) + { + } + + // Standard methods + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_consume); + BOOST_ASSERT(order != memory_order_acquire); + BOOST_ASSERT(order != memory_order_acq_rel); + + core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); + } + + BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); + } + + BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); + } + + BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); + } + + BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT + { + BOOST_ASSERT(failure_order != memory_order_release); + BOOST_ASSERT(failure_order != memory_order_acq_rel); + BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); + + return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); + } + + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + // Boost.Atomic extensions + BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); + } + + BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return atomics::detail::bitwise_cast< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); + } + + BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); + } + + BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); + } + + // Operators + BOOST_FORCEINLINE value_type operator++(int) const BOOST_NOEXCEPT + { + return fetch_add(1); + } + + BOOST_FORCEINLINE value_type operator++() const BOOST_NOEXCEPT + { + return add(1); + } + + BOOST_FORCEINLINE value_type operator--(int) const BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + BOOST_FORCEINLINE value_type operator--() const BOOST_NOEXCEPT + { + return sub(1); + } + + BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT + { + return add(v); + } + + BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT + { + return sub(v); + } + + BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT + { + BOOST_ASSERT(order != memory_order_release); + BOOST_ASSERT(order != memory_order_acq_rel); + + return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order)); + } + + BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) + +private: + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) const BOOST_NOEXCEPT + { + return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + } + + BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) const BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); + const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::bitwise_cast< value_type >(old_value); + return res; + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/bitwise_cast.hpp b/boost/atomic/detail/bitwise_cast.hpp new file mode 100644 index 0000000..3318eb4 --- /dev/null +++ b/boost/atomic/detail/bitwise_cast.hpp @@ -0,0 +1,158 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2013-2018, 2020-2021 Andrey Semashev + */ +/*! + * \file atomic/detail/bitwise_cast.hpp + * + * This header defines \c bitwise_cast used to convert between storage and value types + */ + +#ifndef BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS) + +#if defined(__has_builtin) +#if __has_builtin(__builtin_bit_cast) +#define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y) +#endif +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) && defined(BOOST_MSVC) && BOOST_MSVC >= 1926 +#define BOOST_ATOMIC_DETAIL_BIT_CAST(x, y) __builtin_bit_cast(x, y) +#endif + +#endif // !defined(BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS) + +#if defined(BOOST_NO_CXX11_CONSTEXPR) || !defined(BOOST_ATOMIC_DETAIL_BIT_CAST) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_ADDRESSOF) +#define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_BITWISE_CAST) +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST BOOST_CONSTEXPR +#else +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST +#endif + +#if defined(BOOST_GCC) && BOOST_GCC >= 80000 +#pragma GCC diagnostic push +// copying an object of non-trivial type X from an array of Y. This is benign because we use memcpy to copy trivially copyable objects. +#pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t ValueSize, typename To > +BOOST_FORCEINLINE void clear_tail_padding_bits(To& to, atomics::detail::true_type) BOOST_NOEXCEPT +{ + BOOST_ATOMIC_DETAIL_MEMSET(reinterpret_cast< unsigned char* >(atomics::detail::addressof(to)) + ValueSize, 0, sizeof(To) - ValueSize); +} + +template< std::size_t ValueSize, typename To > +BOOST_FORCEINLINE void clear_tail_padding_bits(To&, atomics::detail::false_type) BOOST_NOEXCEPT +{ +} + +template< std::size_t ValueSize, typename To > +BOOST_FORCEINLINE void clear_tail_padding_bits(To& to) BOOST_NOEXCEPT +{ + atomics::detail::clear_tail_padding_bits< ValueSize >(to, atomics::detail::integral_constant< bool, ValueSize < sizeof(To) >()); +} + +template< typename To, std::size_t FromValueSize, typename From > +BOOST_FORCEINLINE To bitwise_cast_memcpy(From const& from) BOOST_NOEXCEPT +{ + typedef typename atomics::detail::remove_cv< To >::type unqualified_to_t; + unqualified_to_t to; +#if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) + From from2(from); + BOOST_ATOMIC_DETAIL_CLEAR_PADDING(atomics::detail::addressof(from2)); + BOOST_ATOMIC_DETAIL_MEMCPY + ( + atomics::detail::addressof(to), + atomics::detail::addressof(from2), + (FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t)) + ); +#else + BOOST_ATOMIC_DETAIL_MEMCPY + ( + atomics::detail::addressof(to), + atomics::detail::addressof(from), + (FromValueSize < sizeof(unqualified_to_t) ? FromValueSize : sizeof(unqualified_to_t)) + ); +#endif + atomics::detail::clear_tail_padding_bits< FromValueSize >(to); + return to; +} + +#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +template< typename To, std::size_t FromValueSize, typename From > +BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast_impl(From const& from, atomics::detail::true_type) BOOST_NOEXCEPT +{ + // This implementation is only called when the From type has no padding and From and To have the same size + return BOOST_ATOMIC_DETAIL_BIT_CAST(typename atomics::detail::remove_cv< To >::type, from); +} + +template< typename To, std::size_t FromValueSize, typename From > +BOOST_FORCEINLINE To bitwise_cast_impl(From const& from, atomics::detail::false_type) BOOST_NOEXCEPT +{ + return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from); +} + +template< typename To, std::size_t FromValueSize, typename From > +BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT +{ + return atomics::detail::bitwise_cast_impl< To, FromValueSize >(from, atomics::detail::integral_constant< bool, + FromValueSize == sizeof(To) && atomics::detail::has_unique_object_representations< From >::value >()); +} + +#else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +template< typename To, std::size_t FromValueSize, typename From > +BOOST_FORCEINLINE To bitwise_cast(From const& from) BOOST_NOEXCEPT +{ + return atomics::detail::bitwise_cast_memcpy< To, FromValueSize >(from); +} + +#endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +//! Converts the source object to the target type, possibly by padding or truncating it on the right, and clearing any padding bits (if supported by compiler). Preserves value bits unchanged. +template< typename To, typename From > +BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_cast(From const& from) BOOST_NOEXCEPT +{ + return atomics::detail::bitwise_cast< To, sizeof(From) >(from); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#if defined(BOOST_GCC) && BOOST_GCC >= 80000 +#pragma GCC diagnostic pop +#endif + +#include + +#endif // BOOST_ATOMIC_DETAIL_BITWISE_CAST_HPP_INCLUDED_ diff --git a/boost/atomic/detail/bitwise_fp_cast.hpp b/boost/atomic/detail/bitwise_fp_cast.hpp new file mode 100644 index 0000000..3f0ede8 --- /dev/null +++ b/boost/atomic/detail/bitwise_fp_cast.hpp @@ -0,0 +1,118 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018, 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/bitwise_fp_cast.hpp + * + * This header defines \c bitwise_fp_cast used to convert between storage and floating point value types + */ + +#ifndef BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_ + +#include +#include +#include +#include +#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST) +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +/*! + * \brief The type trait returns the size of the value of the specified floating point type + * + * This size may be less than sizeof(T) if the implementation uses padding bytes for a particular FP type. This is + * often the case with 80-bit extended double, which is stored in 12 or 16 initial bytes with tail padding filled with garbage. + */ +template< typename T > +struct value_size_of +{ + static BOOST_CONSTEXPR_OR_CONST std::size_t value = sizeof(T); +}; + +#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE) +template< > +struct value_size_of< float > +{ + static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE; +}; +#endif + +#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE) +template< > +struct value_size_of< double > +{ + static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE; +}; +#endif + +#if defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE) +template< > +struct value_size_of< long double > +{ + static BOOST_CONSTEXPR_OR_CONST std::size_t value = BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE; +}; +#endif + +template< typename T > +struct value_size_of< const T > : value_size_of< T > {}; + +template< typename T > +struct value_size_of< volatile T > : value_size_of< T > {}; + +template< typename T > +struct value_size_of< const volatile T > : value_size_of< T > {}; + + +#if !defined(BOOST_ATOMIC_NO_CLEAR_PADDING) +// BOOST_ATOMIC_DETAIL_CLEAR_PADDING, which is used in bitwise_cast, will clear the tail padding bits in the source object. +// We don't need to specify the actual value size to avoid redundant zeroing of the tail padding. +#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(x) sizeof(x) +#else +#define BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(x) atomics::detail::value_size_of< x >::value +#endif + +#if defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +//! Similar to bitwise_cast, but either \c From or \c To is expected to be a floating point type. Attempts to detect the actual value size in the source object and considers the rest of the object as padding. +template< typename To, typename From > +BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT +{ + // For floating point types, has_unique_object_representations is typically false even if the type contains no padding bits. + // Here, we rely on our detection of the actual value size to select constexpr bit_cast implementation when possible. We assume + // here that floating point value bits are contiguous. + return atomics::detail::bitwise_cast_impl< To, BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(From) >(from, atomics::detail::integral_constant< bool, + atomics::detail::value_size_of< From >::value == sizeof(From) && atomics::detail::value_size_of< From >::value == sizeof(To) >()); +} + +#else // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +//! Similar to bitwise_cast, but either \c From or \c To is expected to be a floating point type. Attempts to detect the actual value size in the source object and considers the rest of the object as padding. +template< typename To, typename From > +BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_BITWISE_CAST To bitwise_fp_cast(From const& from) BOOST_NOEXCEPT +{ + return atomics::detail::bitwise_cast< To, BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_VALUE_SIZE_OF(From) >(from); +} + +#endif // defined(BOOST_ATOMIC_DETAIL_BIT_CAST) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_BITWISE_FP_CAST_HPP_INCLUDED_ diff --git a/boost/atomic/detail/capabilities.hpp b/boost/atomic/detail/capabilities.hpp new file mode 100644 index 0000000..825bfd1 --- /dev/null +++ b/boost/atomic/detail/capabilities.hpp @@ -0,0 +1,217 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/capabilities.hpp + * + * This header defines core feature capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_ + +#include +#include +#include +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) +#include +#endif + +#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/caps_) +#elif defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/caps_arch_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_ATOMIC_INT8_LOCK_FREE +#define BOOST_ATOMIC_INT8_LOCK_FREE 0 +#endif + +#ifndef BOOST_ATOMIC_INT16_LOCK_FREE +#define BOOST_ATOMIC_INT16_LOCK_FREE 0 +#endif + +#ifndef BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_INT32_LOCK_FREE 0 +#endif + +#ifndef BOOST_ATOMIC_INT64_LOCK_FREE +#define BOOST_ATOMIC_INT64_LOCK_FREE 0 +#endif + +#ifndef BOOST_ATOMIC_INT128_LOCK_FREE +#define BOOST_ATOMIC_INT128_LOCK_FREE 0 +#endif + + +#ifndef BOOST_ATOMIC_CHAR_LOCK_FREE +#define BOOST_ATOMIC_CHAR_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#endif + +#ifndef BOOST_ATOMIC_CHAR8_T_LOCK_FREE +#define BOOST_ATOMIC_CHAR8_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#endif + +#ifndef BOOST_ATOMIC_CHAR16_T_LOCK_FREE +#define BOOST_ATOMIC_CHAR16_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#endif + +#ifndef BOOST_ATOMIC_CHAR32_T_LOCK_FREE +#define BOOST_ATOMIC_CHAR32_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#endif + +#ifndef BOOST_ATOMIC_WCHAR_T_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 +#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 +#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 +#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 +#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_WCHAR_T_LOCK_FREE 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_SHORT_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 +#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 +#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 +#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 +#define BOOST_ATOMIC_SHORT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_SHORT_LOCK_FREE 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_INT_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 +#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 +#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 +#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 +#define BOOST_ATOMIC_INT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_INT_LOCK_FREE 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_LONG_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 +#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 +#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 +#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 +#define BOOST_ATOMIC_LONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_LONG_LOCK_FREE 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_LLONG_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 +#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 +#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 +#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 +#define BOOST_ATOMIC_LLONG_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_LLONG_LOCK_FREE 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_POINTER_LOCK_FREE +#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8 +#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4 +#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#else +#define BOOST_ATOMIC_POINTER_LOCK_FREE 0 +#endif +#endif + +#define BOOST_ATOMIC_ADDRESS_LOCK_FREE BOOST_ATOMIC_POINTER_LOCK_FREE + +#ifndef BOOST_ATOMIC_BOOL_LOCK_FREE +// We store bools in 1-byte storage in all backends +#define BOOST_ATOMIC_BOOL_LOCK_FREE BOOST_ATOMIC_INT8_LOCK_FREE +#endif + +#ifndef BOOST_ATOMIC_FLAG_LOCK_FREE +// atomic_flag uses 4-byte storage +#define BOOST_ATOMIC_FLAG_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#endif + +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +#if !defined(BOOST_ATOMIC_FLOAT_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) +#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2 +#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4 +#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8 +#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT <= 16 +#define BOOST_ATOMIC_FLOAT_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE +#else +#define BOOST_ATOMIC_FLOAT_LOCK_FREE 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2 +#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4 +#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8 +#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE <= 16 +#define BOOST_ATOMIC_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE +#else +#define BOOST_ATOMIC_DOUBLE_LOCK_FREE 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2 +#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4 +#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8 +#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE <= 16 +#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE +#else +#define BOOST_ATOMIC_LONG_DOUBLE_LOCK_FREE 0 +#endif +#endif + +#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +#ifndef BOOST_ATOMIC_THREAD_FENCE +#define BOOST_ATOMIC_THREAD_FENCE 0 +#endif + +#ifndef BOOST_ATOMIC_SIGNAL_FENCE +#define BOOST_ATOMIC_SIGNAL_FENCE 0 +#endif + +#endif // BOOST_ATOMIC_DETAIL_CAPABILITIES_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_aarch32.hpp b/boost/atomic/detail/caps_arch_gcc_aarch32.hpp new file mode 100644 index 0000000..769a546 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_aarch32.hpp @@ -0,0 +1,53 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020, 2022 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_aarch32.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__ARMEL__) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + defined(BOOST_WINDOWS) +#define BOOST_ATOMIC_DETAIL_AARCH32_LITTLE_ENDIAN +#elif defined(__ARMEB__) || \ + defined(__ARM_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) +#define BOOST_ATOMIC_DETAIL_AARCH32_BIG_ENDIAN +#else +#include +#if BOOST_ENDIAN_LITTLE_BYTE +#define BOOST_ATOMIC_DETAIL_AARCH32_LITTLE_ENDIAN +#elif BOOST_ENDIAN_BIG_BYTE +#define BOOST_ATOMIC_DETAIL_AARCH32_BIG_ENDIAN +#else +#error "Boost.Atomic: Failed to determine AArch32 endianness, the target platform is not supported. Please, report to the developers (patches are welcome)." +#endif +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH32_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_aarch64.hpp b/boost/atomic/detail/caps_arch_gcc_aarch64.hpp new file mode 100644 index 0000000..d486b10 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_aarch64.hpp @@ -0,0 +1,65 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020, 2022 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_aarch64.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__AARCH64EL__) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + defined(BOOST_WINDOWS) +#define BOOST_ATOMIC_DETAIL_AARCH64_LITTLE_ENDIAN +#elif defined(__AARCH64EB__) || \ + defined(__ARM_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) +#define BOOST_ATOMIC_DETAIL_AARCH64_BIG_ENDIAN +#else +#include +#if BOOST_ENDIAN_LITTLE_BYTE +#define BOOST_ATOMIC_DETAIL_AARCH64_LITTLE_ENDIAN +#elif BOOST_ENDIAN_BIG_BYTE +#define BOOST_ATOMIC_DETAIL_AARCH64_BIG_ENDIAN +#else +#error "Boost.Atomic: Failed to determine AArch64 endianness, the target platform is not supported. Please, report to the developers (patches are welcome)." +#endif +#endif + +#if defined(__ARM_FEATURE_ATOMICS) +// ARMv8.1 added Large System Extensions, which includes cas, swp, and a number of other read-modify-write instructions +#define BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE +#endif + +#if defined(__ARM_FEATURE_COMPLEX) +// ARMv8.3 added Release Consistency processor consistent (RCpc) memory model, which includes ldapr and similar instructions. +// Unfortunately, there seems to be no dedicated __ARM_FEATURE macro for this, so we use __ARM_FEATURE_COMPLEX, which is also defined starting ARMv8.3. +#define BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#define BOOST_ATOMIC_INT128_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_AARCH64_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_alpha.hpp b/boost/atomic/detail/caps_arch_gcc_alpha.hpp new file mode 100644 index 0000000..a73a7c1 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_alpha.hpp @@ -0,0 +1,34 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_alpha.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ALPHA_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_arm.hpp b/boost/atomic/detail/caps_arch_gcc_arm.hpp new file mode 100644 index 0000000..0e3b219 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_arm.hpp @@ -0,0 +1,103 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2009 Phil Endecott + * Copyright (c) 2013 Tim Blechmann + * ARM Code by Phil Endecott, based on other architectures. + * Copyright (c) 2014, 2020, 2022 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_arm.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__ARMEL__) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + defined(BOOST_WINDOWS) +#define BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN +#elif defined(__ARMEB__) || \ + defined(__ARM_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) +#define BOOST_ATOMIC_DETAIL_ARM_BIG_ENDIAN +#else +#include +#if BOOST_ENDIAN_LITTLE_BYTE +#define BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN +#elif BOOST_ENDIAN_BIG_BYTE +#define BOOST_ATOMIC_DETAIL_ARM_BIG_ENDIAN +#else +#error "Boost.Atomic: Failed to determine ARM endianness, the target platform is not supported. Please, report to the developers (patches are welcome)." +#endif +#endif + +#if defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 6) + +#if BOOST_ATOMIC_DETAIL_ARM_ARCH > 6 +// ARMv7 and later have dmb instruction +#define BOOST_ATOMIC_DETAIL_ARM_HAS_DMB 1 +#endif + +#if defined(__ARM_FEATURE_LDREX) + +#if (__ARM_FEATURE_LDREX & 1) +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB 1 +#endif +#if (__ARM_FEATURE_LDREX & 2) +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH 1 +#endif +#if (__ARM_FEATURE_LDREX & 8) +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD 1 +#endif + +#else // defined(__ARM_FEATURE_LDREX) + +#if !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__)) + +// ARMv6k and ARMv7 have 8 and 16-bit ldrex/strex variants, but at least GCC 4.7 fails to compile them. GCC 4.9 is known to work. +#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409 +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB 1 +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH 1 +#endif + +#if !(((defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6ZK__)) && defined(__thumb__)) || defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7M__)) +// ARMv6k and ARMv7 except ARMv7-M have 64-bit ldrex/strex variants. +// Unfortunately, GCC (at least 4.7.3 on Ubuntu) does not allocate register pairs properly when targeting ARMv6k Thumb, +// which is required for ldrexd/strexd instructions, so we disable 64-bit support. When targeting ARMv6k ARM +// or ARMv7 (both ARM and Thumb 2) it works as expected. +#define BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD 1 +#endif + +#endif // !(defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6Z__)) + +#endif // defined(__ARM_FEATURE_LDREX) + +#endif // defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 6) + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#endif +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_ppc.hpp b/boost/atomic/detail/caps_arch_gcc_ppc.hpp new file mode 100644 index 0000000..a4665e6 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_ppc.hpp @@ -0,0 +1,55 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_ppc.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__POWERPC__) || defined(__PPC__) + +#if defined(_ARCH_PWR8) +// Power8 and later architectures have 8 and 16-bit instructions +#define BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX +#define BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX +#endif + +#if defined(__powerpc64__) || defined(__PPC64__) +// Power7 and later architectures in 64-bit mode have 64-bit instructions +#define BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX +#if defined(_ARCH_PWR8) +// Power8 also has 128-bit instructions +#define BOOST_ATOMIC_DETAIL_PPC_HAS_LQARX_STQCX +#endif +#endif + +#endif // defined(__POWERPC__) || defined(__PPC__) + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#endif +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_PPC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_sparc.hpp b/boost/atomic/detail/caps_arch_gcc_sparc.hpp new file mode 100644 index 0000000..9b49301 --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_sparc.hpp @@ -0,0 +1,34 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2010 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_sparc.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_SPARC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_gcc_x86.hpp b/boost/atomic/detail/caps_arch_gcc_x86.hpp new file mode 100644 index 0000000..b705fdc --- /dev/null +++ b/boost/atomic/detail/caps_arch_gcc_x86.hpp @@ -0,0 +1,74 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2013 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_gcc_x86.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) + +#if defined(__i386__) &&\ + (\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) ||\ + defined(__i586__) || defined(__i686__) || defined(__SSE__)\ + ) +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1 +#endif + +#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1 +#endif + +#if defined(__x86_64__) || defined(__SSE2__) +// Use mfence only if SSE2 is available +#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 1 +#endif + +#else // defined(__GNUC__) + +#if defined(__i386__) && !defined(BOOST_ATOMIC_NO_CMPXCHG8B) +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1 +#endif + +#if defined(__x86_64__) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B) +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1 +#endif + +#if !defined(BOOST_ATOMIC_NO_MFENCE) +#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 1 +#endif + +#endif // defined(__GNUC__) + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#if defined(__x86_64__) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#endif +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) +#define BOOST_ATOMIC_INT128_LOCK_FREE 2 +#endif +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_GCC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_msvc_arm.hpp b/boost/atomic/detail/caps_arch_msvc_arm.hpp new file mode 100644 index 0000000..3cfb99d --- /dev/null +++ b/boost/atomic/detail/caps_arch_msvc_arm.hpp @@ -0,0 +1,34 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2012 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_msvc_arm.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_arch_msvc_x86.hpp b/boost/atomic/detail/caps_arch_msvc_x86.hpp new file mode 100644 index 0000000..87b5cb0 --- /dev/null +++ b/boost/atomic/detail/caps_arch_msvc_x86.hpp @@ -0,0 +1,61 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2012 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_arch_msvc_x86.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(_M_IX86) && _M_IX86 >= 500 +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B 1 +#endif + +#if defined(_M_AMD64) && !defined(BOOST_ATOMIC_NO_CMPXCHG16B) +#if defined(__clang__) +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1 +#endif +#elif _MSC_VER >= 1500 +#define BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B 1 +#endif +#endif + +#if defined(_MSC_VER) && (defined(_M_AMD64) || (defined(_M_IX86) && defined(_M_IX86_FP) && _M_IX86_FP >= 2)) +// Use mfence only if SSE2 is available +#define BOOST_ATOMIC_DETAIL_X86_HAS_MFENCE 1 +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 + +#if defined(_M_AMD64) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#endif + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) +#define BOOST_ATOMIC_INT128_LOCK_FREE 2 +#endif + +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_ARCH_MSVC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_gcc_atomic.hpp b/boost/atomic/detail/caps_gcc_atomic.hpp new file mode 100644 index 0000000..2bd7ab4 --- /dev/null +++ b/boost/atomic/detail/caps_gcc_atomic.hpp @@ -0,0 +1,158 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_gcc_atomic.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_ + +#include +#include + +#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/caps_arch_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Translate type-based lock-free macros to size-based ones +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE + +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#else +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE 0 +#endif + +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#else +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE 0 +#endif + +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#else +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE 0 +#endif + +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 16 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 16 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 16 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 16 +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#else +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE 0 +#endif + +// On x86-64, clang 3.4 does not implement 128-bit __atomic* intrinsics even though it defines __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16: +// https://bugs.llvm.org/show_bug.cgi?id=19149 +// Another problem exists with gcc 7 and later, as it requires to link with libatomic to use 16-byte intrinsics: +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878 +// Both clang and gcc do generate cmpxchg16b for __sync_val_compare_and_swap though. +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) &&\ + (\ + (defined(BOOST_CLANG) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 5))) ||\ + (defined(BOOST_GCC) && BOOST_GCC >= 70000)\ + ) +#undef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE 0 +#endif + +// On 32-bit x86, there is a clang bug for 64-bit atomics: https://bugs.llvm.org/show_bug.cgi?id=19355. The compiler defines +// __GCC_ATOMIC_LLONG_LOCK_FREE to 1 when the target architecture supports 64-bit atomic instructions (i.e. the value should be 2). +// Additionally, any clang version requires to link with libatomic for 64-bit __atomic* intrinsics on x86. It does generate +// cmpxchg8b for __sync_val_compare_and_swap though. +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) && defined(BOOST_CLANG) +#undef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE 0 +#endif + +// Override arch-specific macros if atomic intrinsics provide better guarantees +#if !defined(BOOST_ATOMIC_INT128_LOCK_FREE) || (BOOST_ATOMIC_INT128_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE) +#undef BOOST_ATOMIC_INT128_LOCK_FREE +#define BOOST_ATOMIC_INT128_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE +#endif + +#if !defined(BOOST_ATOMIC_INT64_LOCK_FREE) || (BOOST_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE) || (BOOST_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_INT128_LOCK_FREE) +#undef BOOST_ATOMIC_INT64_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT128_LOCK_FREE +#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE +#else +#define BOOST_ATOMIC_INT64_LOCK_FREE BOOST_ATOMIC_INT128_LOCK_FREE +#endif +#endif + +#if !defined(BOOST_ATOMIC_INT32_LOCK_FREE) || (BOOST_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE) || (BOOST_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_INT64_LOCK_FREE) +#undef BOOST_ATOMIC_INT32_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE +#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE +#else +#define BOOST_ATOMIC_INT32_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#endif +#endif + +#if !defined(BOOST_ATOMIC_INT16_LOCK_FREE) || (BOOST_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE) || (BOOST_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_INT32_LOCK_FREE) +#undef BOOST_ATOMIC_INT16_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE +#else +#define BOOST_ATOMIC_INT16_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#endif +#endif + +#if !defined(BOOST_ATOMIC_INT8_LOCK_FREE) || (BOOST_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE) || (BOOST_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_INT16_LOCK_FREE) +#undef BOOST_ATOMIC_INT8_LOCK_FREE +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE +#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE +#else +#define BOOST_ATOMIC_INT8_LOCK_FREE BOOST_ATOMIC_INT16_LOCK_FREE +#endif +#endif + +#if !defined(BOOST_ATOMIC_POINTER_LOCK_FREE) || (BOOST_ATOMIC_POINTER_LOCK_FREE < __GCC_ATOMIC_POINTER_LOCK_FREE) +#undef BOOST_ATOMIC_POINTER_LOCK_FREE +#define BOOST_ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +#if !defined(BOOST_ATOMIC_THREAD_FENCE) || (BOOST_ATOMIC_THREAD_FENCE < 2) +#undef BOOST_ATOMIC_THREAD_FENCE +#define BOOST_ATOMIC_THREAD_FENCE 2 +#endif +#if !defined(BOOST_ATOMIC_SIGNAL_FENCE) || (BOOST_ATOMIC_SIGNAL_FENCE < 2) +#undef BOOST_ATOMIC_SIGNAL_FENCE +#define BOOST_ATOMIC_SIGNAL_FENCE 2 +#endif + +#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_ATOMIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_gcc_sync.hpp b/boost/atomic/detail/caps_gcc_sync.hpp new file mode 100644 index 0000000..43065fe --- /dev/null +++ b/boost/atomic/detail/caps_gcc_sync.hpp @@ -0,0 +1,54 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_gcc_sync.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_INT64_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) +#define BOOST_ATOMIC_INT128_LOCK_FREE 2 +#endif + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_GCC_SYNC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_linux_arm.hpp b/boost/atomic/detail/caps_linux_arm.hpp new file mode 100644 index 0000000..abe6fb8 --- /dev/null +++ b/boost/atomic/detail/caps_linux_arm.hpp @@ -0,0 +1,35 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009, 2011 Helge Bahmann + * Copyright (c) 2009 Phil Endecott + * Copyright (c) 2013 Tim Blechmann + * Linux-specific code by Phil Endecott + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_linux_arm.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_LINUX_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/caps_windows.hpp b/boost/atomic/detail/caps_windows.hpp new file mode 100644 index 0000000..1cc0ded --- /dev/null +++ b/boost/atomic/detail/caps_windows.hpp @@ -0,0 +1,33 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2012 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/caps_windows.hpp + * + * This header defines feature capabilities macros + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#define BOOST_ATOMIC_INT32_LOCK_FREE 2 +#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 + +#define BOOST_ATOMIC_THREAD_FENCE 2 +#define BOOST_ATOMIC_SIGNAL_FENCE 2 + +#endif // BOOST_ATOMIC_DETAIL_CAPS_WINDOWS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/cas_based_exchange.hpp b/boost/atomic/detail/cas_based_exchange.hpp new file mode 100644 index 0000000..ba74dd2 --- /dev/null +++ b/boost/atomic/detail/cas_based_exchange.hpp @@ -0,0 +1,50 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/cas_based_exchange.hpp + * + * This header contains CAS-based implementation of exchange operation. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct cas_based_exchange : + public Base +{ + typedef typename Base::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, v, order, memory_order_relaxed)) {} + return old_val; + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CAS_BASED_EXCHANGE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/classify.hpp b/boost/atomic/detail/classify.hpp new file mode 100644 index 0000000..920e9cf --- /dev/null +++ b/boost/atomic/detail/classify.hpp @@ -0,0 +1,90 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020-2021 Andrey Semashev + */ +/*! + * \file atomic/detail/classify.hpp + * + * This header contains type traits for type classification. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T, bool IsFunction = atomics::detail::is_function< T >::value > +struct classify_pointer +{ + typedef void* type; +}; + +template< typename T > +struct classify_pointer< T, true > +{ + typedef void type; +}; + +template< + typename T, + bool IsInt = atomics::detail::is_integral< T >::value, + bool IsFloat = atomics::detail::is_floating_point< T >::value, + bool IsEnum = atomics::detail::is_enum< T >::value +> +struct classify +{ + typedef void type; +}; + +template< typename T > +struct classify< T, true, false, false > { typedef int type; }; + +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) +template< typename T > +struct classify< T, false, true, false > { typedef float type; }; +#endif + +template< typename T > +struct classify< T, false, false, true > { typedef const int type; }; + +template< typename T > +struct classify< T*, false, false, false > { typedef typename classify_pointer< T >::type type; }; + +template< > +struct classify< void*, false, false, false > { typedef void type; }; + +template< > +struct classify< const void*, false, false, false > { typedef void type; }; + +template< > +struct classify< volatile void*, false, false, false > { typedef void type; }; + +template< > +struct classify< const volatile void*, false, false, false > { typedef void type; }; + +template< typename T, typename U > +struct classify< T U::*, false, false, false > { typedef void type; }; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CLASSIFY_HPP_INCLUDED_ diff --git a/boost/atomic/detail/config.hpp b/boost/atomic/detail/config.hpp new file mode 100644 index 0000000..185f0cc --- /dev/null +++ b/boost/atomic/detail/config.hpp @@ -0,0 +1,143 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2012 Hartmut Kaiser + * Copyright (c) 2014-2018, 2020-2021 Andrey Semashev + */ +/*! + * \file atomic/detail/config.hpp + * + * This header defines configuraion macros for Boost.Atomic + */ + +#ifndef BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__CUDACC__) +// nvcc does not support alternatives ("q,m") in asm statement constraints +#define BOOST_ATOMIC_DETAIL_NO_ASM_CONSTRAINT_ALTERNATIVES +// nvcc does not support condition code register ("cc") clobber in asm statements +#define BOOST_ATOMIC_DETAIL_NO_ASM_CLOBBER_CC +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_ASM_CLOBBER_CC) +#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC "cc" +#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "cc", +#else +#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC +#define BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA +#endif + +#if (defined(__i386__) || defined(__x86_64__)) && (defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC < 40500) || defined(__SUNPRO_CC)) +// This macro indicates that the compiler does not support allocating eax:edx or rax:rdx register pairs ("A") in asm blocks +#define BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS +#endif + +#if defined(__i386__) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC >= 50100)) +// This macro indicates that asm blocks should preserve ebx value unchanged. Some compilers are able to maintain ebx themselves +// around the asm blocks. For those compilers we don't need to save/restore ebx in asm blocks. +#define BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX +#endif + +#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#if !(defined(BOOST_LIBSTDCXX11) && BOOST_LIBSTDCXX_VERSION >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */ +// This macro indicates that there is not even a basic standard header that is sufficient for most Boost.Atomic needs. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS +#endif +#endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + +#if defined(BOOST_NO_CXX11_ALIGNAS) ||\ + (defined(BOOST_GCC) && BOOST_GCC < 40900) ||\ + (defined(BOOST_MSVC) && BOOST_MSVC < 1910 && defined(_M_IX86)) +// gcc prior to 4.9 doesn't support alignas with a constant expression as an argument. +// MSVC 14.0 does support alignas, but in 32-bit mode emits "error C2719: formal parameter with requested alignment of N won't be aligned" for N > 4, +// when aligned types are used in function arguments, even though the std::max_align_t type has alignment of 8. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_ALIGNAS +#endif + +#if defined(BOOST_NO_CXX11_CONSTEXPR) || (defined(BOOST_GCC) && BOOST_GCC < 40800) +// This macro indicates that the compiler doesn't support constexpr constructors that initialize one member +// of an anonymous union member of the class. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_CONSTEXPR_UNION_INIT) +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT BOOST_CONSTEXPR +#else +#define BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT +#endif + +// Enable pointer/reference casts between storage and value when possible. +// Note: Despite that MSVC does not employ strict aliasing rules for optimizations +// and does not require an explicit markup for types that may alias, we still don't +// enable the optimization for this compiler because at least MSVC-8 and 9 are known +// to generate broken code sometimes when casts are used. +#define BOOST_ATOMIC_DETAIL_MAY_ALIAS BOOST_MAY_ALIAS +#if !defined(BOOST_NO_MAY_ALIAS) +#define BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS +#endif + +#if defined(__GCC_ASM_FLAG_OUTPUTS__) +// The compiler supports output values in flag registers. +// See: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html, Section 6.44.3. +#define BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS +#endif + +#if defined(BOOST_INTEL) || (defined(BOOST_GCC) && BOOST_GCC < 40700) ||\ + (defined(BOOST_CLANG) && !defined(__apple_build_version__) && (__clang_major__ * 100 + __clang_minor__) < 302) ||\ + (defined(__clang__) && defined(__apple_build_version__) && (__clang_major__ * 100 + __clang_minor__) < 402) +// Intel compiler (at least 18.0 update 1) breaks if noexcept specification is used in defaulted function declarations: +// error: the default constructor of "boost::atomics::atomic" cannot be referenced -- it is a deleted function +// GCC 4.6 doesn't seem to support that either. Clang 3.1 deduces wrong noexcept for the defaulted function and fails as well. +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL BOOST_NOEXCEPT +#else +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL BOOST_NOEXCEPT +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL +#endif + +#if defined(__has_builtin) +#if __has_builtin(__builtin_constant_p) +#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) +#endif +#if __has_builtin(__builtin_clear_padding) +#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_clear_padding(x) +#elif __has_builtin(__builtin_zero_non_value_bits) +#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_zero_non_value_bits(x) +#endif +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_IS_CONSTANT) && defined(__GNUC__) +#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_IS_CONSTANT) +#define BOOST_ATOMIC_DETAIL_IS_CONSTANT(x) false +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_CLEAR_PADDING) && defined(BOOST_MSVC) && BOOST_MSVC >= 1927 +// Note that as of MSVC 19.29 this intrinsic does not clear padding in unions: +// https://developercommunity.visualstudio.com/t/__builtin_zero_non_value_bits-does-not-c/1551510 +#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) __builtin_zero_non_value_bits(x) +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_CLEAR_PADDING) +#define BOOST_ATOMIC_NO_CLEAR_PADDING +#define BOOST_ATOMIC_DETAIL_CLEAR_PADDING(x) +#endif + +#if (defined(__BYTE_ORDER__) && defined(__FLOAT_WORD_ORDER__) && __BYTE_ORDER__ == __FLOAT_WORD_ORDER__) ||\ + defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) +// This macro indicates that integer and floating point endianness is the same +#define BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH +#endif + +#endif // BOOST_ATOMIC_DETAIL_CONFIG_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_operations.hpp b/boost/atomic/detail/core_arch_operations.hpp new file mode 100644 index 0000000..40a1081 --- /dev/null +++ b/boost/atomic/detail/core_arch_operations.hpp @@ -0,0 +1,50 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_operations.hpp + * + * This header defines core atomic operations, including the emulated version. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/core_arch_ops_) +#endif + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Default specialization that falls back to lock-based implementation +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_arch_operations : + public core_operations_emulated< Size, storage_traits< Size >::alignment, Signed, Interprocess > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_operations_fwd.hpp b/boost/atomic/detail/core_arch_operations_fwd.hpp new file mode 100644 index 0000000..f018fe4 --- /dev/null +++ b/boost/atomic/detail/core_arch_operations_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_operations_fwd.hpp + * + * This header contains forward declaration of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_aarch32.hpp b/boost/atomic/detail/core_arch_ops_gcc_aarch32.hpp new file mode 100644 index 0000000..0e5d7b2 --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_aarch32.hpp @@ -0,0 +1,1121 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_aarch32.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +// ARMv8 (AArch32) instruction set is similar to ARMv7, but adds +// lda(b/h) and ldaex(b/h/d) instructions for acquire loads and +// stl(b/h) and stlex(b/h/d) instructions for release stores. This +// makes explicit memory fences unnecessary for implementation of +// the majority of the atomic operations. +// +// ARMv8 deprecates applying "it" hints to some instructions, including +// strex. It also deprecates "it" hints applying to more than one +// of the following conditional instructions. This means we have to +// use conditional jumps instead of making other instructions conditional. + +struct core_arch_operations_gcc_aarch32_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch32_base +{ + typedef typename storage_traits< 1u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlb %[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "ldab %[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "st" st_mo "exb %[tmp], %[value], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [tmp] "=&r" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)\ + : [value] "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxtb %[expected], %[expected]\n\t"\ + "mov %[success], #0\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 1f\n\t"\ + "st" st_mo "exb %[success], %[desired], %[storage]\n\t"\ + "eor %[success], %[success], #1\n\t"\ + "1:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "r" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxtb %[expected], %[expected]\n\t"\ + "mov %[success], #0\n\t"\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 2f\n\t"\ + "st" st_mo "exb %[success], %[desired], %[storage]\n\t"\ + "eors %[success], %[success], #1\n\t"\ + "beq 1b\n\t"\ + "2:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "r" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "add %[result], %[original], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "sub %[result], %[original], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "and %[result], %[original], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "orr %[result], %[original], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "eor %[result], %[original], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch32_base +{ + typedef typename storage_traits< 2u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlh %[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "ldah %[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "st" st_mo "exh %[tmp], %[value], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [tmp] "=&r" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)\ + : [value] "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxth %[expected], %[expected]\n\t"\ + "mov %[success], #0\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 1f\n\t"\ + "st" st_mo "exh %[success], %[desired], %[storage]\n\t"\ + "eor %[success], %[success], #1\n\t"\ + "1:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "r" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxth %[expected], %[expected]\n\t"\ + "mov %[success], #0\n\t"\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 2f\n\t"\ + "st" st_mo "exh %[success], %[desired], %[storage]\n\t"\ + "eors %[success], %[success], #1\n\t"\ + "beq 1b\n\t"\ + "2:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "r" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "add %[result], %[original], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "sub %[result], %[original], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "and %[result], %[original], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "orr %[result], %[original], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "eor %[result], %[original], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch32_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stl %[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "lda %[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "st" st_mo "ex %[tmp], %[value], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [tmp] "=&r" (tmp), [original] "=&r" (original), [storage] "+Q" (storage)\ + : [value] "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %[success], #0\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 1f\n\t"\ + "st" st_mo "ex %[success], %[desired], %[storage]\n\t"\ + "eor %[success], %[success], #1\n\t"\ + "1:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "Ir" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %[success], #0\n\t"\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "cmp %[original], %[expected]\n\t"\ + "bne 2f\n\t"\ + "st" st_mo "ex %[success], %[desired], %[storage]\n\t"\ + "eors %[success], %[success], #1\n\t"\ + "beq 1b\n\t"\ + "2:\n\t"\ + : [original] "=&r" (original), [success] "=&r" (success), [storage] "+Q" (storage)\ + : [expected] "Ir" (expected), [desired] "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "add %[result], %[original], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "sub %[result], %[original], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "and %[result], %[original], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "orr %[result], %[original], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "eor %[result], %[original], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + + +// Unlike 32-bit operations, for 64-bit loads and stores we must use ldrexd/strexd. +// Other instructions result in a non-atomic sequence of 32-bit or more fine-grained accesses. +// See "ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile", Section E2.2 "Atomicity in the ARM architecture". +// Section E2.3.7 "Memory barriers", subsection "Load-Acquire, Store-Release" extends atomicity guarantees given for ldrexd/strexd +// to the new ldaexd/stlexd instructions with acquire/release semantics. +// +// In the asm blocks below we have to use 32-bit register pairs to compose 64-bit values. In order to pass the 64-bit operands +// to/from asm blocks, we use undocumented gcc feature: the lower half (Rt) of the operand is accessible normally, via the numbered +// placeholder (e.g. %0), and the upper half (Rt2) - via the same placeholder with an 'H' after the '%' sign (e.g. %H0). +// See: http://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/ +// +// The ldrexd and strexd instructions operate on pairs of registers, meaning that each load loads two integers from memory in +// successive address order, to the first and second registers in the pair, respectively, and store similarly stores two integers. +// The order of these integers does not depend on the active endianness mode (although the byte order in the integers themselves +// obviously does depend on endianness). This means we need to account for the current endianness mode ourselves, where it matters. + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch32_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + exchange(storage, v, order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "ldaexd %0, %H0, %1\n\t" + : "=&r" (original) // %0 + : "Q" (storage) // %1 + ); + } + else + { + __asm__ __volatile__ + ( + "ldrexd %0, %H0, %1\n\t" + : "=&r" (original) // %0 + : "Q" (storage) // %1 + ); + } + + return original; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %1, %H1, %2\n\t"\ + "st" st_mo "exd %0, %3, %H3, %2\n\t"\ + "teq %0, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (tmp), "=&r" (original), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %1, #0\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "cmp %0, %3\n\t"\ + "it eq\n\t"\ + "cmpeq %H0, %H3\n\t"\ + "bne 1f\n\t"\ + "st" st_mo "exd %1, %4, %H4, %2\n\t"\ + "eor %1, %1, #1\n\t"\ + "1:\n\t"\ + : "=&r" (original), "=&r" (success), "+Q" (storage)\ + : "r" (expected), "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; + bool success; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %1, #0\n\t"\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "cmp %0, %3\n\t"\ + "it eq\n\t"\ + "cmpeq %H0, %H3\n\t"\ + "bne 2f\n\t"\ + "st" st_mo "exd %1, %4, %H4, %2\n\t"\ + "eors %1, %1, #1\n\t"\ + "beq 1b\n\t"\ + "2:\n\t"\ + : "=&r" (original), "=&r" (success), "+Q" (storage)\ + : "r" (expected), "r" (desired)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + expected = original; + + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(4) "\n\t"\ + "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(4) "\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "subs " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(4) "\n\t"\ + "sbc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(4) "\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "and %3, %0, %4\n\t"\ + "and %H3, %H0, %H4\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "orr %3, %0, %4\n\t"\ + "orr %H3, %H0, %H4\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "eor %3, %0, %4\n\t"\ + "eor %H3, %H0, %H4\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_aarch64.hpp b/boost/atomic/detail/core_arch_ops_gcc_aarch64.hpp new file mode 100644 index 0000000..192cf6e --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_aarch64.hpp @@ -0,0 +1,1909 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_aarch64.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct core_arch_operations_gcc_aarch64_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; +}; + +// Due to bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63359 we have to explicitly specify size of the registers +// to use in the asm blocks below. Use %w prefix for the 32-bit registers and %x for 64-bit ones. + +// A note about compare_exchange implementations. Since failure_order must never include release semantics and +// must not be stronger than success_order, we can always use success_order to select instructions. Thus, when +// CAS fails, only the acquire semantics of success_order is applied, which may be stronger than failure_order. + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch64_base +{ + typedef typename storage_traits< 1u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlrb %w[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC) + if (order == memory_order_consume || order == memory_order_acquire) + { + __asm__ __volatile__ + ( + "ldaprb %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else +#endif + { + __asm__ __volatile__ + ( + "ldarb %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "swp" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[value], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo "b %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxtb %w[expected], %w[expected]\n\t"\ + "mov %w[success], #0\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 1f\n\t"\ + "st" st_mo "xrb %w[success], %w[desired], %[storage]\n\t"\ + "eor %w[success], %w[success], #1\n\t"\ + "1:\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "r" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo "b %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxtb %w[expected], %w[expected]\n\t"\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 2f\n\t"\ + "st" st_mo "xrb %w[success], %w[desired], %[storage]\n\t"\ + "cbnz %w[success], 1b\n\t"\ + "2:\n\t"\ + "cset %w[success], eq\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "r" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "add %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = -v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); + +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "sub %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = ~v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldclr" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "and %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldset" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "orr %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldeor" ld_mo st_mo "b %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "eor %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch64_base +{ + typedef typename storage_traits< 2u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlrh %w[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC) + if (order == memory_order_consume || order == memory_order_acquire) + { + __asm__ __volatile__ + ( + "ldaprh %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else +#endif + { + __asm__ __volatile__ + ( + "ldarh %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "swp" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[value], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo "h %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxth %w[expected], %w[expected]\n\t"\ + "mov %w[success], #0\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 1f\n\t"\ + "st" st_mo "xrh %w[success], %w[desired], %[storage]\n\t"\ + "eor %w[success], %w[success], #1\n\t"\ + "1:\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "r" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo "h %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "uxth %w[expected], %w[expected]\n\t"\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 2f\n\t"\ + "st" st_mo "xrh %w[success], %w[desired], %[storage]\n\t"\ + "cbnz %w[success], 1b\n\t"\ + "2:\n\t"\ + "cset %w[success], eq\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "r" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "add %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = -v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); + +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "sub %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = ~v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldclr" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "and %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldset" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "orr %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldeor" ld_mo st_mo "h %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "eor %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch64_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlr %w[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC) + if (order == memory_order_consume || order == memory_order_acquire) + { + __asm__ __volatile__ + ( + "ldapr %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else +#endif + { + __asm__ __volatile__ + ( + "ldar %w[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "swp" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "st" st_mo "xr %w[tmp], %w[value], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo " %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %w[success], #0\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 1f\n\t"\ + "st" st_mo "xr %w[success], %w[desired], %[storage]\n\t"\ + "eor %w[success], %w[success], #1\n\t"\ + "1:\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "Ir" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo " %w[original], %w[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "cmp %w[original], %w[expected]\n\t"\ + "b.ne 2f\n\t"\ + "st" st_mo "xr %w[success], %w[desired], %[storage]\n\t"\ + "cbnz %w[success], 1b\n\t"\ + "2:\n\t"\ + "cset %w[success], eq\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "Ir" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "add %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = -v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); + +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "sub %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = ~v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldclr" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "and %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldset" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "orr %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldeor" ld_mo st_mo " %w[value], %w[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "eor %w[result], %w[original], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Kr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch64_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + { + __asm__ __volatile__ + ( + "stlr %x[value], %[storage]\n\t" + : [storage] "=Q" (storage) + : [value] "r" (v) + : "memory" + ); + } + else + { + storage = v; + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC) + if (order == memory_order_consume || order == memory_order_acquire) + { + __asm__ __volatile__ + ( + "ldapr %x[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + else +#endif + { + __asm__ __volatile__ + ( + "ldar %x[value], %[storage]\n\t" + : [value] "=r" (v) + : [storage] "Q" (storage) + : "memory" + ); + } + } + else + { + v = storage; + } + + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "swp" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "st" st_mo "xr %w[tmp], %x[value], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo " %x[original], %x[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %w[success], #0\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "cmp %x[original], %x[expected]\n\t"\ + "b.ne 1f\n\t"\ + "st" st_mo "xr %w[success], %x[desired], %[storage]\n\t"\ + "eor %w[success], %w[success], #1\n\t"\ + "1:\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "Ir" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + original = expected; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "cas" ld_mo st_mo " %x[original], %x[desired], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "+r" (original)\ + : [desired] "r" (desired)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) + bool success = original == expected; +#else + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "cmp %x[original], %x[expected]\n\t"\ + "b.ne 2f\n\t"\ + "st" st_mo "xr %w[success], %x[desired], %[storage]\n\t"\ + "cbnz %w[success], 1b\n\t"\ + "2:\n\t"\ + "cset %w[success], eq\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [desired] "r" (desired), [expected] "Ir" (expected)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#endif +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "add %x[result], %x[original], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = -v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldadd" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); + +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "sub %x[result], %x[original], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Ir" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + v = ~v; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldclr" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "and %x[result], %x[original], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Lr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldset" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "orr %x[result], %x[original], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Lr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "ldeor" ld_mo st_mo " %x[value], %x[original], %[storage]\n\t"\ + : [storage] "+Q" (storage), [original] "=r" (original)\ + : [value] "r" (v)\ + : "memory"\ + ); +#else + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "eor %x[result], %x[original], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : [value] "Lr" (v)\ + : "memory"\ + ); +#endif + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +// For 128-bit atomic operations we always have to use ldxp+stxp (optionally, with acquire/release semantics), even in load and store operations. +// ARM Architecture Reference Manual Armv8, for Armv8-A architecture profile, Section B2.2.1 "Requirements for single-copy atomicity" +// specifies that ldxp does not guarantee an atomic load, and we have to perform ldxp+stxp loop to ensure that the loaded value +// is consistent with a previous atomic store. +// +// The ldxp and stxp instructions operate on pairs of registers, meaning that each load loads two integers from memory in +// successive address order, to the first and second registers in the pair, respectively, and store similarly stores two integers. +// The order of these integers does not depend on the active endianness mode (although the byte order in the integers themselves +// obviously does depend on endianness). This means we need to account for the current endianness mode ourselves, where it matters. +// +// Unlike AArch32/A32 or ARMv7, ldxp/stxp do not require adjacent even+odd registers in the pair and accept any two different +// registers. Still, it may be more preferable to select the adjacent registers as 128-bit objects are represented by two adjacent +// registers in the ABI. Unfortunately, clang 10 and probably older doesn't seem to support allocating register pairs in the asm blocks, +// like in ARMv7. For now we use a union to convert between a pair of 64-bit elements and 128-bit storage. + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 16u, Signed, Interprocess > : + public core_arch_operations_gcc_aarch64_base +{ + typedef typename storage_traits< 16u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 16u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + // Union to convert between two 64-bit registers and a 128-bit storage + union storage_union + { + storage_type as_storage; + uint64_t as_uint64[2u]; + }; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + exchange(storage, v, order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_union v; + uint32_t tmp; + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "1:\n\t" + "ldaxp %x[value_0], %x[value_1], %[storage]\n\t" + "stxp %w[tmp], %x[value_0], %x[value_1], %[storage]\n\t" + "cbnz %w[tmp], 1b\n\t" + : [tmp] "=&r" (tmp), [value_0] "=&r" (v.as_uint64[0u]), [value_1] "=&r" (v.as_uint64[1u]) + : [storage] "Q" (storage) + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "1:\n\t" + "ldxp %x[value_0], %x[value_1], %[storage]\n\t" + "stxp %w[tmp], %x[value_0], %x[value_1], %[storage]\n\t" + "cbnz %w[tmp], 1b\n\t" + : [tmp] "=&r" (tmp), [value_0] "=&r" (v.as_uint64[0u]), [value_1] "=&r" (v.as_uint64[1u]) + : [storage] "Q" (storage) + : "memory" + ); + } + + return v.as_storage; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "st" st_mo "xp %w[tmp], %x[value_0], %x[value_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u])\ + : [value_0] "r" (value.as_uint64[0u]), [value_1] "r" (value.as_uint64[1u])\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_union original; + storage_union e = { expected }; + storage_union d = { desired }; + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "mov %w[success], #0\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "cmp %x[original_0], %x[expected_0]\n\t"\ + "ccmp %x[original_1], %x[expected_1], #0, eq\n\t"\ + "b.ne 1f\n\t"\ + "st" st_mo "xp %w[success], %x[desired_0], %x[desired_1], %[storage]\n\t"\ + "eor %w[success], %w[success], #1\n\t"\ + "1:\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u])\ + : [desired_0] "r" (d.as_uint64[0u]), [desired_1] "r" (d.as_uint64[1u]), [expected_0] "r" (e.as_uint64[0u]), [expected_1] "r" (e.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original.as_storage; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_union original; + storage_union e = { expected }; + storage_union d = { desired }; + bool success; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "cmp %x[original_0], %x[expected_0]\n\t"\ + "ccmp %x[original_1], %x[expected_1], #0, eq\n\t"\ + "b.ne 2f\n\t"\ + "st" st_mo "xp %w[success], %x[desired_0], %x[desired_1], %[storage]\n\t"\ + "cbnz %w[success], 1b\n\t"\ + "2:\n\t"\ + "cset %w[success], eq\n\t"\ + : [success] "=&r" (success), [storage] "+Q" (storage), [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u])\ + : [desired_0] "r" (d.as_uint64[0u]), [desired_1] "r" (d.as_uint64[1u]), [expected_0] "r" (e.as_uint64[0u]), [expected_1] "r" (e.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(success_order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + expected = original.as_storage; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "adds %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[original_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "]\n\t"\ + "adc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[original_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "r" (value.as_uint64[0u]), [value_1] "r" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "subs %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[original_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "]\n\t"\ + "sbc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[original_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "r" (value.as_uint64[0u]), [value_1] "r" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "and %x[result_0], %x[original_0], %x[value_0]\n\t"\ + "and %x[result_1], %x[original_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "orr %x[result_0], %x[original_0], %x[value_0]\n\t"\ + "orr %x[result_1], %x[original_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union value = { v }; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "eor %x[result_0], %x[original_0], %x[value_0]\n\t"\ + "eor %x[result_1], %x[original_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_alpha.hpp b/boost/atomic/detail/core_arch_ops_gcc_alpha.hpp new file mode 100644 index 0000000..9f29ab0 --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_alpha.hpp @@ -0,0 +1,867 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_alpha.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +/* + Refer to http://h71000.www7.hp.com/doc/82final/5601/5601pro_004.html + (HP OpenVMS systems documentation) and the Alpha Architecture Reference Manual. + */ + +/* + NB: The most natural thing would be to write the increment/decrement + operators along the following lines: + + __asm__ __volatile__ + ( + "1: ldl_l %0,%1 \n" + "addl %0,1,%0 \n" + "stl_c %0,%1 \n" + "beq %0,1b\n" + : "=&b" (tmp) + : "m" (value) + : "cc" + ); + + However according to the comments on the HP website and matching + comments in the Linux kernel sources this defies branch prediction, + as the cpu assumes that backward branches are always taken; so + instead copy the trick from the Linux kernel, introduce a forward + branch and back again. + + I have, however, had a hard time measuring the difference between + the two versions in microbenchmarks -- I am leaving it in nevertheless + as it apparently does not hurt either. +*/ + +struct core_arch_operations_gcc_alpha_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __asm__ __volatile__ ("mb" ::: "memory"); + } + + static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + __asm__ __volatile__ ("mb" ::: "memory"); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("mb" ::: "memory"); + } +}; + + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_alpha_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, tmp; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "mov %3, %1\n\t" + "ldl_l %0, %2\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (tmp) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + int success; + storage_type current; + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %2, %4\n\t" // current = *(&storage) + "cmpeq %2, %0, %3\n\t" // success = current == expected + "mov %2, %0\n\t" // expected = current + "beq %3, 2f\n\t" // if (success == 0) goto end + "stl_c %1, %4\n\t" // storage = desired; desired = store succeeded + "mov %1, %3\n\t" // success = desired + "2:\n\t" + : "+r" (expected), // %0 + "+r" (desired), // %1 + "=&r" (current), // %2 + "=&r" (success) // %3 + : "m" (storage) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + storage_type current, tmp; + fence_before(success_order); + __asm__ __volatile__ + ( + "1:\n\t" + "mov %5, %1\n\t" // tmp = desired + "ldl_l %2, %4\n\t" // current = *(&storage) + "cmpeq %2, %0, %3\n\t" // success = current == expected + "mov %2, %0\n\t" // expected = current + "beq %3, 2f\n\t" // if (success == 0) goto end + "stl_c %1, %4\n\t" // storage = tmp; tmp = store succeeded + "beq %1, 3f\n\t" // if (tmp == 0) goto retry + "mov %1, %3\n\t" // success = tmp + "2:\n\t" + + ".subsection 2\n\t" + "3: br 1b\n\t" + ".previous\n\t" + + : "+r" (expected), // %0 + "=&r" (tmp), // %1 + "=&r" (current), // %2 + "=&r" (success) // %3 + : "m" (storage), // %4 + "r" (desired) // %5 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "addl %0, %3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "subl %0, %3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "and %0, %3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "bis %0, %3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "xor %0, %3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, 0, order); + } +}; + + +template< bool Interprocess > +struct core_arch_operations< 1u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "addl %0, %3, %1\n\t" + "zapnot %1, 1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "subl %0, %3, %1\n\t" + "zapnot %1, 1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 1u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "addl %0, %3, %1\n\t" + "sextb %1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "subl %0, %3, %1\n\t" + "sextb %1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + + +template< bool Interprocess > +struct core_arch_operations< 2u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "addl %0, %3, %1\n\t" + "zapnot %1, 3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "subl %0, %3, %1\n\t" + "zapnot %1, 3, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 2u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "addl %0, %3, %1\n\t" + "sextw %1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + base_type::fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldl_l %0, %2\n\t" + "subl %0, %3, %1\n\t" + "sextw %1, %1\n\t" + "stl_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_alpha_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, tmp; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "mov %3, %1\n\t" + "ldq_l %0, %2\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (tmp) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + int success; + storage_type current; + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %2, %4\n\t" // current = *(&storage) + "cmpeq %2, %0, %3\n\t" // success = current == expected + "mov %2, %0\n\t" // expected = current + "beq %3, 2f\n\t" // if (success == 0) goto end + "stq_c %1, %4\n\t" // storage = desired; desired = store succeeded + "mov %1, %3\n\t" // success = desired + "2:\n\t" + : "+r" (expected), // %0 + "+r" (desired), // %1 + "=&r" (current), // %2 + "=&r" (success) // %3 + : "m" (storage) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + storage_type current, tmp; + fence_before(success_order); + __asm__ __volatile__ + ( + "1:\n\t" + "mov %5, %1\n\t" // tmp = desired + "ldq_l %2, %4\n\t" // current = *(&storage) + "cmpeq %2, %0, %3\n\t" // success = current == expected + "mov %2, %0\n\t" // expected = current + "beq %3, 2f\n\t" // if (success == 0) goto end + "stq_c %1, %4\n\t" // storage = tmp; tmp = store succeeded + "beq %1, 3f\n\t" // if (tmp == 0) goto retry + "mov %1, %3\n\t" // success = tmp + "2:\n\t" + + ".subsection 2\n\t" + "3: br 1b\n\t" + ".previous\n\t" + + : "+r" (expected), // %0 + "=&r" (tmp), // %1 + "=&r" (current), // %2 + "=&r" (success) // %3 + : "m" (storage), // %4 + "r" (desired) // %5 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %0, %2\n\t" + "addq %0, %3, %1\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %0, %2\n\t" + "subq %0, %3, %1\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %0, %2\n\t" + "and %0, %3, %1\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %0, %2\n\t" + "bis %0, %3, %1\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, modified; + fence_before(order); + __asm__ __volatile__ + ( + "1:\n\t" + "ldq_l %0, %2\n\t" + "xor %0, %3, %1\n\t" + "stq_c %1, %2\n\t" + "beq %1, 2f\n\t" + + ".subsection 2\n\t" + "2: br 1b\n\t" + ".previous\n\t" + + : "=&r" (original), // %0 + "=&r" (modified) // %1 + : "m" (storage), // %2 + "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_arm.hpp b/boost/atomic/detail/core_arch_ops_gcc_arm.hpp new file mode 100644 index 0000000..271a26a --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_arm.hpp @@ -0,0 +1,1417 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_arm.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +// From the ARM Architecture Reference Manual for architecture v6: +// +// LDREX{} , [] +// Specifies the destination register for the memory word addressed by +// Specifies the register containing the address. +// +// STREX{} , , [] +// Specifies the destination register for the returned status value. +// 0 if the operation updates memory +// 1 if the operation fails to update memory +// Specifies the register containing the word to be stored to memory. +// Specifies the register containing the address. +// Rd must not be the same register as Rm or Rn. +// +// ARM v7 is like ARM v6 plus: +// There are half-word and byte versions of the LDREX and STREX instructions, +// LDREXH, LDREXB, STREXH and STREXB. +// There are also double-word versions, LDREXD and STREXD. +// (Actually it looks like these are available from version 6k onwards.) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_arm_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // load the original value + "strex %[tmp], %[value], %[storage]\n\t" // store the replacement, tmp = store failed + "teq %[tmp], #0\n\t" // check if store succeeded + "bne 1b\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage) + : [value] "r" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "itt eq\n\t" // [hint that the following 2 instructions are conditional on flags.equal] + "strexeq %[success], %[desired], %[storage]\n\t" // if (flags.equal) *(&storage) = desired, success = store failed + "eoreq %[success], %[success], #1\n\t" // if (flags.equal) success ^= 1 (i.e. make it 1 if store succeeded) + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (expected), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "bne 2f\n\t" // if (!flags.equal) goto end + "strex %[success], %[desired], %[storage]\n\t" // *(&storage) = desired, success = store failed + "eors %[success], %[success], #1\n\t" // success ^= 1 (i.e. make it 1 if store succeeded); flags.equal = success == 0 + "beq 1b\n\t" // if (flags.equal) goto retry + "2:\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (expected), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_gcc_arm_base +{ + typedef typename storage_traits< 1u >::type storage_type; + typedef typename storage_traits< 4u >::type extended_storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + extended_storage_type original; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // load the original value and zero-extend to 32 bits + "strexb %[tmp], %[value], %[storage]\n\t" // store the replacement, tmp = store failed + "teq %[tmp], #0\n\t" // check if store succeeded + "bne 1b\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage) + : [value] "r" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + extended_storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "itt eq\n\t" // [hint that the following 2 instructions are conditional on flags.equal] + "strexbeq %[success], %[desired], %[storage]\n\t" // if (flags.equal) *(&storage) = desired, success = store failed + "eoreq %[success], %[success], #1\n\t" // if (flags.equal) success ^= 1 (i.e. make it 1 if store succeeded) + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = static_cast< storage_type >(original); + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + extended_storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "bne 2f\n\t" // if (!flags.equal) goto end + "strexb %[success], %[desired], %[storage]\n\t" // *(&storage) = desired, success = store failed + "eors %[success], %[success], #1\n\t" // success ^= 1 (i.e. make it 1 if store succeeded); flags.equal = success == 0 + "beq 1b\n\t" // if (flags.equal) goto retry + "2:\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = static_cast< storage_type >(original); + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#else // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) + +template< bool Interprocess > +struct core_arch_operations< 1u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "uxtb %[result], %[result]\n\t" // zero extend result from 8 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "uxtb %[result], %[result]\n\t" // zero extend result from 8 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 1u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "sxtb %[result], %[result]\n\t" // sign extend result from 8 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "sxtb %[result], %[result]\n\t" // sign extend result from 8 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_gcc_arm_base +{ + typedef typename storage_traits< 2u >::type storage_type; + typedef typename storage_traits< 4u >::type extended_storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + extended_storage_type original; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // load the original value and zero-extend to 32 bits + "strexh %[tmp], %[value], %[storage]\n\t" // store the replacement, tmp = store failed + "teq %[tmp], #0\n\t" // check if store succeeded + "bne 1b\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [tmp] "=&l" (tmp), [original] "=&r" (original), [storage] "+Q" (storage) + : [value] "r" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + extended_storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "itt eq\n\t" // [hint that the following 2 instructions are conditional on flags.equal] + "strexheq %[success], %[desired], %[storage]\n\t" // if (flags.equal) *(&storage) = desired, success = store failed + "eoreq %[success], %[success], #1\n\t" // if (flags.equal) success ^= 1 (i.e. make it 1 if store succeeded) + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = static_cast< storage_type >(original); + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + bool success = false; +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + uint32_t tmp; +#endif + extended_storage_type original; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "cmp %[original], %[expected]\n\t" // flags = original==expected + "bne 2f\n\t" // if (!flags.equal) goto end + "strexh %[success], %[desired], %[storage]\n\t" // *(&storage) = desired, success = store failed + "eors %[success], %[success], #1\n\t" // success ^= 1 (i.e. make it 1 if store succeeded); flags.equal = success == 0 + "beq 1b\n\t" // if (flags.equal) goto retry + "2:\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), + [success] "+r" (success), +#if !defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + [tmp] "=&l" (tmp), +#endif + [storage] "+Q" (storage) + : [expected] "Ir" (atomics::detail::zero_extend< extended_storage_type >(expected)), + [desired] "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = static_cast< storage_type >(original); + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#else // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) + +template< bool Interprocess > +struct core_arch_operations< 2u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "uxth %[result], %[result]\n\t" // zero extend result from 16 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "uxth %[result], %[result]\n\t" // zero extend result from 16 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 2u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "sxth %[result], %[result]\n\t" // sign extend result from 16 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "sxth %[result], %[result]\n\t" // sign extend result from 16 to 32 bits + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) + +// Unlike 32-bit operations, for 64-bit loads and stores we must use ldrexd/strexd. +// Any other instructions result in a non-atomic sequence of 32-bit accesses. +// See "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition", +// Section A3.5.3 "Atomicity in the ARM architecture". + +// In the asm blocks below we have to use 32-bit register pairs to compose 64-bit values. +// In order to pass the 64-bit operands to/from asm blocks, we use undocumented gcc feature: +// the lower half (Rt) of the operand is accessible normally, via the numbered placeholder (e.g. %0), +// and the upper half (Rt2) - via the same placeholder with an 'H' after the '%' sign (e.g. %H0). +// See: http://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/ + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_arm_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + exchange(storage, v, order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + // ARMv7 says ldrex (and other load-exclusive instructions) can be used without a matching strex, see + // "ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition", Section A3.4.5 "Load-Exclusive and Store-Exclusive usage restrictions". + storage_type original; +#if defined(BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED) + __asm__ __volatile__ + ( + "ldrexd %0, %H0, %1\n\t" + : "=&r" (original) // %0 + : "Q" (storage) // %1 + ); +#else + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "ldrexd %1, %H1, %2\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original) // %1 + : "Q" (storage) // %2 + ); +#endif + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %2\n\t" // load the original value + "strexd %0, %3, %H3, %2\n\t" // store the replacement, tmp = store failed + "teq %0, #0\n\t" // check if store succeeded + "bne 1b\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "+Q" (storage) // %2 + : "r" (v) // %3 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + storage_type original; + bool success = false; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "cmp %1, %4\n\t" // flags = original.lo==expected.lo + "it eq\n\t" // [hint that the following 1 instruction is conditional on flags.equal] + "cmpeq %H1, %H4\n\t" // if (flags.equal) flags = original.hi==expected.hi + "bne 1f\n\t" + "strexd %2, %5, %H5, %3\n\t" // *(&storage) = desired, success = store failed + "eor %2, %2, #1\n\t" // success ^= 1 (i.e. make it 1 if store succeeded) + "1:\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "+r" (success), // %2 + "+Q" (storage) // %3 + : "r" (expected), // %4 + "r" (desired) // %5 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = original; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + storage_type original; + bool success = false; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "cmp %1, %4\n\t" // flags = original.lo==expected.lo + "it eq\n\t" // [hint that the following 1 instruction is conditional on flags.equal] + "cmpeq %H1, %H4\n\t" // if (flags.equal) flags = original.hi==expected.hi + "bne 2f\n\t" + "strexd %2, %5, %H5, %3\n\t" // *(&storage) = desired, success = store failed + "eors %2, %2, #1\n\t" // success ^= 1 (i.e. make it 1 if store succeeded), flags.equal = success == 0 + "beq 1b\n\t" // if (flags.equal) goto retry + "2:\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "+r" (success), // %2 + "+Q" (storage) // %3 + : "r" (expected), // %4 + "r" (desired) // %5 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = original; + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "adds " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t" // result = original + value + "adc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "subs " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t" // result = original - value + "sbc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "and %2, %1, %4\n\t" // result = original & value + "and %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "orr %2, %1, %4\n\t" // result = original | value + "orr %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "eor %2, %1, %4\n\t" // result = original ^ value + "eor %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_ppc.hpp b/boost/atomic/detail/core_arch_ops_gcc_ppc.hpp new file mode 100644 index 0000000..a35c4ad --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_ppc.hpp @@ -0,0 +1,1218 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_ppc.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +// The implementation below uses information from this document: +// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2010.02.19a.html + +/* + Refer to: Motorola: "Programming Environments Manual for 32-Bit + Implementations of the PowerPC Architecture", Appendix E: + "Synchronization Programming Examples" for an explanation of what is + going on here (can be found on the web at various places by the + name "MPCFPE32B.pdf", Google is your friend...) + + Most of the atomic operations map to instructions in a relatively + straight-forward fashion, but "load"s may at first glance appear + a bit strange as they map to: + + lwz %rX, addr + cmpw %rX, %rX + bne- 1f + 1: + + That is, the CPU is forced to perform a branch that "formally" depends + on the value retrieved from memory. This scheme has an overhead of + about 1-2 clock cycles per load, but it allows to map "acquire" to + the "isync" instruction instead of "sync" uniformly and for all type + of atomic operations. Since "isync" has a cost of about 15 clock + cycles, while "sync" hast a cost of about 50 clock cycles, the small + penalty to atomic loads more than compensates for this. + + Byte- and halfword-sized atomic values are implemented in two ways. + When 8 and 16-bit instructions are available (in Power8 and later), + they are used. Otherwise operations are realized by encoding the + value to be represented into a word, performing sign/zero extension + as appropriate. This means that after add/sub operations the value + needs fixing up to accurately preserve the wrap-around semantic of + the smaller type. (Nothing special needs to be done for the bit-wise + and the "exchange type" operators as the compiler already sees to + it that values carried in registers are extended appropriately and + everything falls into place naturally). + + The register constraint "b" instructs gcc to use any register + except r0; this is sometimes required because the encoding for + r0 is used to signify "constant zero" in a number of instructions, + making r0 unusable in this place. For simplicity this constraint + is used everywhere since I am to lazy to look this up on a + per-instruction basis, and ppc has enough registers for this not + to pose a problem. +*/ + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_ppc_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + __asm__ __volatile__ + ( + "stw %1, %0\n\t" + : "+m" (storage) + : "r" (v) + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("sync" ::: "memory"); + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "lwz %0, %1\n\t" + "cmpw %0, %0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4") + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "isync\n\t" + : "=&r" (v) + : "m" (storage) + : "cr0", "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lwz %0, %1\n\t" + : "=&r" (v) + : "m" (storage) + ); + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y1\n\t" + "stwcx. %2,%y1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8") + : "=&b" (original), "+Z" (storage) + : "b" (v) + : "cr0" + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + "lwarx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stwcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0") + "lwarx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stwcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_gcc_ppc_base +{ + typedef typename storage_traits< 1u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 1u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 1u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + __asm__ __volatile__ + ( + "stb %1, %0\n\t" + : "+m" (storage) + : "r" (v) + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("sync" ::: "memory"); + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "lbz %0, %1\n\t" + "cmpw %0, %0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4") + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "isync\n\t" + : "=&r" (v) + : "m" (storage) + : "cr0", "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lbz %0, %1\n\t" + : "=&r" (v) + : "m" (storage) + ); + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y1\n\t" + "stbcx. %2,%y1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8") + : "=&b" (original), "+Z" (storage) + : "b" (v) + : "cr0" + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + "lbarx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stbcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0") + "lbarx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stbcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) + +template< bool Interprocess > +struct core_arch_operations< 1u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "rlwinm %1, %1, 0, 0xff\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "rlwinm %1, %1, 0, 0xff\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 1u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "extsb %1, %1\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "extsb %1, %1\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_gcc_ppc_base +{ + typedef typename storage_traits< 2u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 2u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 2u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + __asm__ __volatile__ + ( + "sth %1, %0\n\t" + : "+m" (storage) + : "r" (v) + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("sync" ::: "memory"); + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "lhz %0, %1\n\t" + "cmpw %0, %0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4") + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "isync\n\t" + : "=&r" (v) + : "m" (storage) + : "cr0", "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lhz %0, %1\n\t" + : "=&r" (v) + : "m" (storage) + ); + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y1\n\t" + "sthcx. %2,%y1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8") + : "=&b" (original), "+Z" (storage) + : "b" (v) + : "cr0" + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + "lharx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "sthcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0") + "lharx %0,%y2\n\t" + "cmpw %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "sthcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#else // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) + +template< bool Interprocess > +struct core_arch_operations< 2u, false, Interprocess > : + public core_arch_operations< 4u, false, Interprocess > +{ + typedef core_arch_operations< 4u, false, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "rlwinm %1, %1, 0, 0xffff\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "rlwinm %1, %1, 0, 0xffff\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +template< bool Interprocess > +struct core_arch_operations< 2u, true, Interprocess > : + public core_arch_operations< 4u, true, Interprocess > +{ + typedef core_arch_operations< 4u, true, Interprocess > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "extsh %1, %1\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + base_type::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "extsh %1, %1\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-16") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + base_type::fence_after(order); + return original; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_ppc_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + __asm__ __volatile__ + ( + "std %1, %0\n\t" + : "+m" (storage) + : "r" (v) + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v; + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("sync" ::: "memory"); + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + { + __asm__ __volatile__ + ( + "ld %0, %1\n\t" + "cmpd %0, %0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+4") + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "isync\n\t" + : "=&b" (v) + : "m" (storage) + : "cr0", "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "ld %0, %1\n\t" + : "=&b" (v) + : "m" (storage) + ); + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y1\n\t" + "stdcx. %2,%y1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-8") + : "=&b" (original), "+Z" (storage) + : "b" (v) + : "cr0" + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + "ldarx %0,%y2\n\t" + "cmpd %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stdcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+8") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + int success; + fence_before(success_order); + __asm__ __volatile__ + ( + "li %1, 0\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("0") + "ldarx %0,%y2\n\t" + "cmpd %0, %3\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1f", "+16") + "stdcx. %4,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "0b", "-16") + "li %1, 1\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + : "=&b" (expected), "=&b" (success), "+Z" (storage) + : "b" (expected), "b" (desired) + : "cr0" + ); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + return !!success; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + fence_after(order); + return original; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_sparc.hpp b/boost/atomic/detail/core_arch_ops_gcc_sparc.hpp new file mode 100644 index 0000000..aad7ec7 --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_sparc.hpp @@ -0,0 +1,215 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2010 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_sparc.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct gcc_sparc_cas_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("membar #Sync" ::: "memory"); + else if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory"); + } + + static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("membar #Sync" ::: "memory"); + else if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + __asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory"); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("membar #Sync" ::: "memory"); + } +}; + +template< bool Signed, bool Interprocess > +struct gcc_sparc_cas32 : + public gcc_sparc_cas_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + storage_type previous = expected; + __asm__ __volatile__ + ( + "cas [%1], %2, %0" + : "+r" (desired) + : "r" (&storage), "r" (previous) + : "memory" + ); + const bool success = (desired == previous); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = desired; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + __asm__ __volatile__ + ( + "swap [%1], %0" + : "+r" (v) + : "r" (&storage) + : "memory" + ); + fence_after(order); + return v; + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_operations_cas_based< gcc_sparc_cas32< Signed, Interprocess > > +{ +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 1u, Signed > +{ +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 2u, Signed > +{ +}; + +template< bool Signed, bool Interprocess > +struct gcc_sparc_cas64 : + public gcc_sparc_cas_base +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + fence_before(success_order); + storage_type previous = expected; + __asm__ __volatile__ + ( + "casx [%1], %2, %0" + : "+r" (desired) + : "r" (&storage), "r" (previous) + : "memory" + ); + const bool success = (desired == previous); + if (success) + fence_after(success_order); + else + fence_after(failure_order); + expected = desired; + return success; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_operations_cas_based< cas_based_exchange< gcc_sparc_cas64< Signed, Interprocess > > > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_gcc_x86.hpp b/boost/atomic/detail/core_arch_ops_gcc_x86.hpp new file mode 100644 index 0000000..b0e3936 --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_gcc_x86.hpp @@ -0,0 +1,1110 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_gcc_x86.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) +#include +#include +#include +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct core_arch_operations_gcc_x86_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __asm__ __volatile__ ("" ::: "memory"); + } + + static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +template< std::size_t Size, bool Signed, bool Interprocess, typename Derived > +struct core_arch_operations_gcc_x86 : + public core_arch_operations_gcc_x86_base +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = Size; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_seq_cst) + { + fence_before(order); + storage = v; + fence_after(order); + } + else + { + Derived::exchange(storage, v, order); + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return Derived::fetch_add(storage, -v, order); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!Derived::exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_gcc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > +{ + typedef core_arch_operations_gcc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type temp_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xaddb %0, %1" + : "+q" (v), "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "xchgb %0, %1" + : "+q" (v), "+m" (storage) + : + : "memory" + ); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + bool success; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgb %3, %1" + : "+a" (previous), "+m" (storage), "=@ccz" (success) + : "q" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgb %3, %1\n\t" + "sete %2" + : "+a" (previous), "+m" (storage), "=q" (success) + : "q" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + expected = previous; + return success; + } + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\ + temp_storage_type new_val;\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %2\n\t"\ + op " %%al, %b2\n\t"\ + "lock; cmpxchgb %b2, %[storage]\n\t"\ + "jne 1b"\ + : [res] "+a" (result), [storage] "+m" (storage), "=&q" (new_val)\ + : [arg] "ir" ((temp_storage_type)argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andb", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orb", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorb", v, res); + return res; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_gcc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > +{ + typedef core_arch_operations_gcc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type temp_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xaddw %0, %1" + : "+q" (v), "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "xchgw %0, %1" + : "+q" (v), "+m" (storage) + : + : "memory" + ); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + bool success; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgw %3, %1" + : "+a" (previous), "+m" (storage), "=@ccz" (success) + : "q" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgw %3, %1\n\t" + "sete %2" + : "+a" (previous), "+m" (storage), "=q" (success) + : "q" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + expected = previous; + return success; + } + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\ + temp_storage_type new_val;\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %2\n\t"\ + op " %%ax, %w2\n\t"\ + "lock; cmpxchgw %w2, %[storage]\n\t"\ + "jne 1b"\ + : [res] "+a" (result), [storage] "+m" (storage), "=&q" (new_val)\ + : [arg] "ir" ((temp_storage_type)argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andw", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orw", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorw", v, res); + return res; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_gcc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > +{ + typedef core_arch_operations_gcc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xaddl %0, %1" + : "+r" (v), "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "xchgl %0, %1" + : "+r" (v), "+m" (storage) + : + : "memory" + ); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + bool success; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgl %3, %1" + : "+a" (previous), "+m" (storage), "=@ccz" (success) + : "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgl %3, %1\n\t" + "sete %2" + : "+a" (previous), "+m" (storage), "=q" (success) + : "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + expected = previous; + return success; + } + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\ + storage_type new_val;\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %[new_val]\n\t"\ + op " %%eax, %[new_val]\n\t"\ + "lock; cmpxchgl %[new_val], %[storage]\n\t"\ + "jne 1b"\ + : [res] "+a" (result), [storage] "+m" (storage), [new_val] "=&r" (new_val)\ + : [arg] "ir" (argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andl", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orl", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorl", v, res); + return res; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP +}; + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) + +// Note: In the 32-bit PIC code guarded with BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX below we have to avoid using memory +// operand constraints because the compiler may choose to use ebx as the base register for that operand. At least, clang +// is known to do that. For this reason we have to pre-compute a pointer to storage and pass it in edi. For the same reason +// we cannot save ebx to the stack with a mov instruction, so we use esi as a scratch register and restore it afterwards. +// Alternatively, we could push/pop the register to the stack, but exchanging the registers is faster. +// The need to pass a pointer in edi is a bit wasteful because normally the memory operand would use a base pointer +// with an offset (e.g. `this` + offset). But unfortunately, there seems to be no way around it. + +template< bool Signed, bool Interprocess > +struct gcc_dcas_x86 +{ + typedef typename storage_traits< 8u >::type storage_type; + typedef uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS aliasing_uint32_t; +#if defined(__SSE2__) + typedef uint32_t xmm_t __attribute__((__vector_size__(16))); +#elif defined(__SSE__) + typedef float xmm_t __attribute__((__vector_size__(16))); +#endif + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if (BOOST_LIKELY(order != memory_order_seq_cst && (((uintptr_t)&storage) & 7u) == 0u)) + { +#if defined(__SSE__) +#if defined(__SSE2__) + xmm_t value = { static_cast< uint32_t >(v), static_cast< uint32_t >(v >> 32u), 0u, 0u }; +#else + xmm_t value; + BOOST_ATOMIC_DETAIL_MEMSET(&value, 0, sizeof(value)); + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(v)); +#endif + __asm__ __volatile__ + ( +#if defined(__AVX__) + "vmovq %[value], %[storage]\n\t" +#elif defined(__SSE2__) + "movq %[value], %[storage]\n\t" +#else + "movlps %[value], %[storage]\n\t" +#endif + : [storage] "=m" (storage) + : [value] "x" (value) + : "memory" + ); +#else // defined(__SSE__) + __asm__ __volatile__ + ( + "fildll %[value]\n\t" + "fistpll %[storage]\n\t" + : [storage] "=m" (storage) + : [value] "m" (v) + : "memory" + ); +#endif // defined(__SSE__) + } + else + { +#if defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + __asm__ __volatile__ + ( + "xchgl %%ebx, %%esi\n\t" + "movl %%eax, %%ebx\n\t" + "movl (%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b (%[dest])\n\t" + "jne 1b\n\t" + "xchgl %%ebx, %%esi\n\t" + : + : "a" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)), [dest] "D" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "edx", "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + __asm__ __volatile__ + ( + "movl %[dest_lo], %%eax\n\t" + "movl %[dest_hi], %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b %[dest_lo]\n\t" + "jne 1b\n\t" + : [dest_lo] "=m" (storage), [dest_hi] "=m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1]) + : [value_lo] "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "eax", "edx", "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type value; + + if (BOOST_LIKELY((((uintptr_t)&storage) & 7u) == 0u)) + { +#if defined(__SSE__) + xmm_t v; + __asm__ __volatile__ + ( +#if defined(__AVX__) + "vmovq %[storage], %[value]\n\t" +#elif defined(__SSE2__) + "movq %[storage], %[value]\n\t" +#else + "xorps %[value], %[value]\n\t" + "movlps %[storage], %[value]\n\t" +#endif + : [value] "=x" (v) + : [storage] "m" (storage) + : "memory" + ); +#if defined(__SSE2__) && (!defined(BOOST_GCC) || BOOST_GCC >= 40800) + // gcc prior to 4.8 don't support subscript operator for vector types + value = static_cast< storage_type >(v[0]) | (static_cast< storage_type >(v[1]) << 32u); +#else + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(value)); +#endif +#else // defined(__SSE__) + __asm__ __volatile__ + ( + "fildll %[storage]\n\t" + "fistpll %[value]\n\t" + : [value] "=m" (value) + : [storage] "m" (storage) + : "memory" + ); +#endif // defined(__SSE__) + } + else + { + // Note that despite const qualification cmpxchg8b below may issue a store to the storage. The storage value + // will not change, but this prevents the storage to reside in read-only memory. + +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + uint32_t value_bits[2]; + + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. + __asm__ __volatile__ + ( + "movl %%ebx, %%eax\n\t" + "movl %%ecx, %%edx\n\t" + "lock; cmpxchg8b %[storage]\n\t" + : "=&a" (value_bits[0]), "=&d" (value_bits[1]) + : [storage] "m" (storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + value = static_cast< storage_type >(value_bits[0]) | (static_cast< storage_type >(value_bits[1]) << 32u); + +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. + __asm__ __volatile__ + ( + "movl %%ebx, %%eax\n\t" + "movl %%ecx, %%edx\n\t" + "lock; cmpxchg8b %[storage]\n\t" + : "=&A" (value) + : [storage] "m" (storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + } + + return value; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { +#if defined(__clang__) + + // Clang cannot allocate eax:edx register pairs but it has sync intrinsics + storage_type old_expected = expected; + expected = __sync_val_compare_and_swap(&storage, old_expected, desired); + return expected == old_expected; + +#elif defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + + bool success; + +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "xchgl %%ebx, %%esi\n\t" + "lock; cmpxchg8b (%[dest])\n\t" + "xchgl %%ebx, %%esi\n\t" + : "+A" (expected), [success] "=@ccz" (success) + : "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32u)), [dest] "D" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "xchgl %%ebx, %%esi\n\t" + "lock; cmpxchg8b (%[dest])\n\t" + "xchgl %%ebx, %%esi\n\t" + "sete %[success]\n\t" + : "+A" (expected), [success] "=qm" (success) + : "S" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32u)), [dest] "D" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + + return success; + +#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + + bool success; + +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchg8b %[dest]\n\t" + : "+A" (expected), [dest] "+m" (storage), [success] "=@ccz" (success) + : "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32u)) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchg8b %[dest]\n\t" + "sete %[success]\n\t" + : "+A" (expected), [dest] "+m" (storage), [success] "=qm" (success) + : "b" ((uint32_t)desired), "c" ((uint32_t)(desired >> 32u)) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + + return success; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + uint32_t old_bits[2]; + __asm__ __volatile__ + ( + "xchgl %%ebx, %%esi\n\t" + "movl (%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b (%[dest])\n\t" + "jne 1b\n\t" + "xchgl %%ebx, %%esi\n\t" + : "=a" (old_bits[0]), "=d" (old_bits[1]) + : "S" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)), [dest] "D" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + storage_type old_value; + BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value)); + return old_value; + +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + storage_type old_value; + __asm__ __volatile__ + ( + "xchgl %%ebx, %%esi\n\t" + "movl (%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b (%[dest])\n\t" + "jne 1b\n\t" + "xchgl %%ebx, %%esi\n\t" + : "=A" (old_value) + : "S" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)), [dest] "D" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return old_value; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) +#else // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) +#if defined(__MINGW32__) && ((__GNUC__+0) * 100 + (__GNUC_MINOR__+0)) < 407 + + // MinGW gcc up to 4.6 has problems with allocating registers in the asm blocks below + uint32_t old_bits[2]; + __asm__ __volatile__ + ( + "movl (%[dest]), %%eax\n\t" + "movl 4(%[dest]), %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b (%[dest])\n\t" + "jne 1b\n\t" + : "=&a" (old_bits[0]), "=&d" (old_bits[1]) + : "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)), [dest] "DS" (&storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + storage_type old_value; + BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value)); + return old_value; + +#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + uint32_t old_bits[2]; + __asm__ __volatile__ + ( + "movl %[dest_lo], %%eax\n\t" + "movl %[dest_hi], %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b %[dest_lo]\n\t" + "jne 1b\n\t" + : "=&a" (old_bits[0]), "=&d" (old_bits[1]), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1]) + : "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + storage_type old_value; + BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value)); + return old_value; + +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + storage_type old_value; + __asm__ __volatile__ + ( + "movl %[dest_lo], %%eax\n\t" + "movl %[dest_hi], %%edx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg8b %[dest_lo]\n\t" + "jne 1b\n\t" + : "=&A" (old_value), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint32_t* >(&storage)[1]) + : "b" ((uint32_t)v), "c" ((uint32_t)(v >> 32u)) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return old_value; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) +#endif // defined(BOOST_ATOMIC_DETAIL_X86_ASM_PRESERVE_EBX) + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_operations_cas_based< gcc_dcas_x86< Signed, Interprocess > > +{ +}; + +#elif defined(__x86_64__) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_gcc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > +{ + typedef core_arch_operations_gcc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xaddq %0, %1" + : "+r" (v), "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "xchgq %0, %1" + : "+r" (v), "+m" (storage) + : + : "memory" + ); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + bool success; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgq %3, %1" + : "+a" (previous), "+m" (storage), "=@ccz" (success) + : "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchgq %3, %1\n\t" + "sete %2" + : "+a" (previous), "+m" (storage), "=q" (success) + : "r" (desired) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + expected = previous; + return success; + } + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, result)\ + storage_type new_val;\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: movq %[arg], %[new_val]\n\t"\ + op " %%rax, %[new_val]\n\t"\ + "lock; cmpxchgq %[new_val], %[storage]\n\t"\ + "jne 1b"\ + : [res] "+a" (result), [storage] "+m" (storage), [new_val] "=&r" (new_val)\ + : [arg] "r" (argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andq", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orq", v, res); + return res; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type res = storage; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorq", v, res); + return res; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP +}; + +#endif + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +template< bool Signed, bool Interprocess > +struct gcc_dcas_x86_64 +{ + typedef typename storage_traits< 16u >::type storage_type; + typedef uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS aliasing_uint64_t; +#if defined(__AVX__) + typedef uint64_t __attribute__((__vector_size__(16))) xmm_t; +#endif + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 16u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(__AVX__) + if (BOOST_LIKELY(order != memory_order_seq_cst && (((uintptr_t)&storage) & 15u) == 0u)) + { + // According to SDM Volume 3, 8.1.1 Guaranteed Atomic Operations, processors supporting AVX guarantee + // aligned vector moves to be atomic. +#if defined(BOOST_HAS_INT128) + xmm_t value = { static_cast< uint64_t >(v), static_cast< uint64_t >(v >> 64u) }; +#else + xmm_t value; + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(v)); +#endif + __asm__ __volatile__ + ( + "vmovdqa %[value], %[storage]\n\t" + : [storage] "=m" (storage) + : [value] "x" (value) + : "memory" + ); + + return; + } +#endif // defined(__AVX__) + + __asm__ __volatile__ + ( + "movq %[dest_lo], %%rax\n\t" + "movq %[dest_hi], %%rdx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg16b %[dest_lo]\n\t" + "jne 1b\n\t" + : [dest_lo] "=m" (storage), [dest_hi] "=m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1]) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "rax", "rdx", "memory" + ); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { +#if defined(__AVX__) + if (BOOST_LIKELY((((uintptr_t)&storage) & 15u) == 0u)) + { + // According to SDM Volume 3, 8.1.1 Guaranteed Atomic Operations, processors supporting AVX guarantee + // aligned vector moves to be atomic. + xmm_t v; + __asm__ __volatile__ + ( + "vmovdqa %[storage], %[value]\n\t" + : [value] "=x" (v) + : [storage] "m" (storage) + : "memory" + ); + +#if defined(BOOST_HAS_INT128) && (!defined(BOOST_GCC) || BOOST_GCC >= 40800) + // gcc prior to 4.8 don't support subscript operator for vector types + storage_type value = static_cast< storage_type >(v[0]) | (static_cast< storage_type >(v[1]) << 64u); +#else + storage_type value; + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(v)); +#endif + return value; + } +#endif // defined(__AVX__) + + // Note that despite const qualification cmpxchg16b below may issue a store to the storage. The storage value + // will not change, but this prevents the storage to reside in read-only memory. + +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + uint64_t value_bits[2]; + + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b. + __asm__ __volatile__ + ( + "movq %%rbx, %%rax\n\t" + "movq %%rcx, %%rdx\n\t" + "lock; cmpxchg16b %[storage]\n\t" + : "=&a" (value_bits[0]), "=&d" (value_bits[1]) + : [storage] "m" (storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + +#if defined(BOOST_HAS_INT128) + storage_type value = static_cast< storage_type >(value_bits[0]) | (static_cast< storage_type >(value_bits[1]) << 64u); +#else + storage_type value; + BOOST_ATOMIC_DETAIL_MEMCPY(&value, value_bits, sizeof(value)); +#endif + return value; + +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + storage_type value; + + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for rbx and rcx values, they just have to be equal to rax and rdx before cmpxchg16b. + __asm__ __volatile__ + ( + "movq %%rbx, %%rax\n\t" + "movq %%rcx, %%rdx\n\t" + "lock; cmpxchg16b %[storage]\n\t" + : "=&A" (value) + : [storage] "m" (storage) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + return value; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { +#if defined(__clang__) + + // Clang cannot allocate rax:rdx register pairs but it has sync intrinsics + storage_type old_expected = expected; + expected = __sync_val_compare_and_swap(&storage, old_expected, desired); + return expected == old_expected; + +#elif defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + // Some compilers can't allocate rax:rdx register pair either but also don't support 128-bit __sync_val_compare_and_swap + bool success; + __asm__ __volatile__ + ( + "lock; cmpxchg16b %[dest]\n\t" + "sete %[success]\n\t" + : [dest] "+m" (storage), "+a" (reinterpret_cast< aliasing_uint64_t* >(&expected)[0]), "+d" (reinterpret_cast< aliasing_uint64_t* >(&expected)[1]), [success] "=q" (success) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + return success; + +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + + bool success; + +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchg16b %[dest]\n\t" + : "+A" (expected), [dest] "+m" (storage), "=@ccz" (success) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#else // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; cmpxchg16b %[dest]\n\t" + "sete %[success]\n\t" + : "+A" (expected), [dest] "+m" (storage), [success] "=qm" (success) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&desired)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif // defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + + return success; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + uint64_t old_bits[2]; + __asm__ __volatile__ + ( + "movq %[dest_lo], %%rax\n\t" + "movq %[dest_hi], %%rdx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg16b %[dest_lo]\n\t" + "jne 1b\n\t" + : [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1]), "=&a" (old_bits[0]), "=&d" (old_bits[1]) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + +#if defined(BOOST_HAS_INT128) + storage_type old_value = static_cast< storage_type >(old_bits[0]) | (static_cast< storage_type >(old_bits[1]) << 64u); +#else + storage_type old_value; + BOOST_ATOMIC_DETAIL_MEMCPY(&old_value, old_bits, sizeof(old_value)); +#endif + return old_value; +#else // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + storage_type old_value; + __asm__ __volatile__ + ( + "movq %[dest_lo], %%rax\n\t" + "movq %[dest_hi], %%rdx\n\t" + ".align 16\n\t" + "1: lock; cmpxchg16b %[dest_lo]\n\t" + "jne 1b\n\t" + : "=&A" (old_value), [dest_lo] "+m" (storage), [dest_hi] "+m" (reinterpret_cast< volatile aliasing_uint64_t* >(&storage)[1]) + : "b" (reinterpret_cast< const aliasing_uint64_t* >(&v)[0]), "c" (reinterpret_cast< const aliasing_uint64_t* >(&v)[1]) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + + return old_value; +#endif // defined(BOOST_ATOMIC_DETAIL_X86_NO_ASM_AX_DX_PAIRS) + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 16u, Signed, Interprocess > : + public core_operations_cas_based< gcc_dcas_x86_64< Signed, Interprocess > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_msvc_arm.hpp b/boost/atomic/detail/core_arch_ops_msvc_arm.hpp new file mode 100644 index 0000000..b8fe201 --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_msvc_arm.hpp @@ -0,0 +1,828 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_msvc_arm.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +extern "C" { +__int8 __iso_volatile_load8(const volatile __int8*); +__int16 __iso_volatile_load16(const volatile __int16*); +__int32 __iso_volatile_load32(const volatile __int32*); +__int64 __iso_volatile_load64(const volatile __int64*); +void __iso_volatile_store8(volatile __int8*, __int8); +void __iso_volatile_store16(volatile __int16*, __int16); +void __iso_volatile_store32(volatile __int32*, __int32); +void __iso_volatile_store64(volatile __int64*, __int64); +} +#if defined(BOOST_MSVC) +#pragma intrinsic(__iso_volatile_load8) +#pragma intrinsic(__iso_volatile_load16) +#pragma intrinsic(__iso_volatile_load32) +#pragma intrinsic(__iso_volatile_load64) +#pragma intrinsic(__iso_volatile_store8) +#pragma intrinsic(__iso_volatile_store16) +#pragma intrinsic(__iso_volatile_store32) +#pragma intrinsic(__iso_volatile_store64) +#endif + +#define BOOST_ATOMIC_DETAIL_ARM_LOAD8(p) __iso_volatile_load8((const volatile __int8*)(p)) +#define BOOST_ATOMIC_DETAIL_ARM_LOAD16(p) __iso_volatile_load16((const volatile __int16*)(p)) +#define BOOST_ATOMIC_DETAIL_ARM_LOAD32(p) __iso_volatile_load32((const volatile __int32*)(p)) +#define BOOST_ATOMIC_DETAIL_ARM_LOAD64(p) __iso_volatile_load64((const volatile __int64*)(p)) +#define BOOST_ATOMIC_DETAIL_ARM_STORE8(p, v) __iso_volatile_store8((volatile __int8*)(p), (__int8)(v)) +#define BOOST_ATOMIC_DETAIL_ARM_STORE16(p, v) __iso_volatile_store16((volatile __int16*)(p), (__int16)(v)) +#define BOOST_ATOMIC_DETAIL_ARM_STORE32(p, v) __iso_volatile_store32((volatile __int32*)(p), (__int32)(v)) +#define BOOST_ATOMIC_DETAIL_ARM_STORE64(p, v) __iso_volatile_store64((volatile __int64*)(p), (__int64)(v)) + +namespace boost { +namespace atomics { +namespace detail { + +// A note about memory_order_consume. Technically, this architecture allows to avoid +// unnecessary memory barrier after consume load since it supports data dependency ordering. +// However, some compiler optimizations may break a seemingly valid code relying on data +// dependency tracking by injecting bogus branches to aid out of order execution. +// This may happen not only in Boost.Atomic code but also in user's code, which we have no +// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php. +// For this reason we promote memory_order_consume to memory_order_acquire. + +struct core_arch_operations_msvc_arm_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + fence_arch_operations::hardware_full_fence(); + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + if (order == memory_order_seq_cst) + fence_arch_operations::hardware_full_fence(); + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + fence_arch_operations::hardware_full_fence(); + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order cas_common_order(memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + // Combine order flags together and promote memory_order_consume to memory_order_acquire + return static_cast< memory_order >(((static_cast< unsigned int >(failure_order) | static_cast< unsigned int >(success_order)) & ~static_cast< unsigned int >(memory_order_consume)) + | (((static_cast< unsigned int >(failure_order) | static_cast< unsigned int >(success_order)) & static_cast< unsigned int >(memory_order_consume)) << 1u)); + } +}; + +template< std::size_t Size, bool Signed, bool Interprocess, typename Derived > +struct core_arch_operations_msvc_arm : + public core_arch_operations_msvc_arm_base +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; + return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!Derived::exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + Derived::store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_msvc_arm< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_arm< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before_store(order); + BOOST_ATOMIC_DETAIL_ARM_STORE8(&storage, v); + base_type::fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD8(&storage); + base_type::fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type previous = expected, old_val; + + switch (base_type::cas_common_order(success_order, failure_order)) + { + case memory_order_relaxed: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELAXED(&storage, desired, previous)); + break; + case memory_order_consume: + case memory_order_acquire: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_ACQUIRE(&storage, desired, previous)); + break; + case memory_order_release: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELEASE(&storage, desired, previous)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous)); + break; + } + expected = old_val; + + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v)); + break; + } + return v; + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_msvc_arm< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_arm< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before_store(order); + BOOST_ATOMIC_DETAIL_ARM_STORE16(&storage, v); + base_type::fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD16(&storage); + base_type::fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type previous = expected, old_val; + + switch (base_type::cas_common_order(success_order, failure_order)) + { + case memory_order_relaxed: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELAXED(&storage, desired, previous)); + break; + case memory_order_consume: + case memory_order_acquire: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_ACQUIRE(&storage, desired, previous)); + break; + case memory_order_release: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELEASE(&storage, desired, previous)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous)); + break; + } + expected = old_val; + + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v)); + break; + } + return v; + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_msvc_arm< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_arm< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before_store(order); + BOOST_ATOMIC_DETAIL_ARM_STORE32(&storage, v); + base_type::fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD32(&storage); + base_type::fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type previous = expected, old_val; + + switch (base_type::cas_common_order(success_order, failure_order)) + { + case memory_order_relaxed: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELAXED(&storage, desired, previous)); + break; + case memory_order_consume: + case memory_order_acquire: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_ACQUIRE(&storage, desired, previous)); + break; + case memory_order_release: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELEASE(&storage, desired, previous)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous)); + break; + } + expected = old_val; + + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v)); + break; + } + return v; + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_msvc_arm< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_arm< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before_store(order); + BOOST_ATOMIC_DETAIL_ARM_STORE64(&storage, v); + base_type::fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = BOOST_ATOMIC_DETAIL_ARM_LOAD64(&storage); + base_type::fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type previous = expected, old_val; + + switch (base_type::cas_common_order(success_order, failure_order)) + { + case memory_order_relaxed: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELAXED(&storage, desired, previous)); + break; + case memory_order_consume: + case memory_order_acquire: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_ACQUIRE(&storage, desired, previous)); + break; + case memory_order_release: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELEASE(&storage, desired, previous)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous)); + break; + } + expected = old_val; + + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v)); + break; + } + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_relaxed: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_RELAXED(&storage, v)); + break; + case memory_order_consume: + case memory_order_acquire: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_ACQUIRE(&storage, v)); + break; + case memory_order_release: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64_RELEASE(&storage, v)); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v)); + break; + } + return v; + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#undef BOOST_ATOMIC_DETAIL_ARM_LOAD8 +#undef BOOST_ATOMIC_DETAIL_ARM_LOAD16 +#undef BOOST_ATOMIC_DETAIL_ARM_LOAD32 +#undef BOOST_ATOMIC_DETAIL_ARM_LOAD64 +#undef BOOST_ATOMIC_DETAIL_ARM_STORE8 +#undef BOOST_ATOMIC_DETAIL_ARM_STORE16 +#undef BOOST_ATOMIC_DETAIL_ARM_STORE32 +#undef BOOST_ATOMIC_DETAIL_ARM_STORE64 + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_arch_ops_msvc_x86.hpp b/boost/atomic/detail/core_arch_ops_msvc_x86.hpp new file mode 100644 index 0000000..197512a --- /dev/null +++ b/boost/atomic/detail/core_arch_ops_msvc_x86.hpp @@ -0,0 +1,903 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_arch_ops_msvc_x86.hpp + * + * This header contains implementation of the \c core_arch_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) || defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) +#include +#include +#include +#endif +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) && defined(__AVX__) +#include +#include +#endif +#include +#if !defined(_M_IX86) && !(defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) && defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16)) +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +/* + * Implementation note for asm blocks. + * + * http://msdn.microsoft.com/en-us/data/k1a8ss06%28v=vs.105%29 + * + * Some SSE types require eight-byte stack alignment, forcing the compiler to emit dynamic stack-alignment code. + * To be able to access both the local variables and the function parameters after the alignment, the compiler + * maintains two frame pointers. If the compiler performs frame pointer omission (FPO), it will use EBP and ESP. + * If the compiler does not perform FPO, it will use EBX and EBP. To ensure code runs correctly, do not modify EBX + * in asm code if the function requires dynamic stack alignment as it could modify the frame pointer. + * Either move the eight-byte aligned types out of the function, or avoid using EBX. + * + * Since we have no way of knowing that the compiler uses FPO, we have to always save and restore ebx + * whenever we have to clobber it. Additionally, we disable warning C4731 in header.hpp so that the compiler + * doesn't spam about ebx use. + */ + +struct core_arch_operations_msvc_x86_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void fence_after_load(memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + // On x86 and x86_64 there is no need for a hardware barrier, + // even if seq_cst memory order is requested, because all + // seq_cst writes are implemented with lock-prefixed operations + // or xchg which has implied lock prefix. Therefore normal loads + // are already ordered with seq_cst stores on these architectures. + } +}; + +template< std::size_t Size, bool Signed, bool Interprocess, typename Derived > +struct core_arch_operations_msvc_x86 : + public core_arch_operations_msvc_x86_base +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_seq_cst) + { + fence_before(order); + storage = v; + fence_after(order); + } + else + { + Derived::exchange(storage, v, order); + } + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; + return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!Derived::exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 4u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 4u, Signed, Interprocess, core_arch_operations< 4u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous)); + expected = old_val; + return (previous == old_val); + } + +#if defined(BOOST_ATOMIC_INTERLOCKED_AND) + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v)); + } +#else + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {} + return res; + } +#endif + +#if defined(BOOST_ATOMIC_INTERLOCKED_OR) + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v)); + } +#else + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {} + return res; + } +#endif + +#if defined(BOOST_ATOMIC_INTERLOCKED_XOR) + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v)); + } +#else + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {} + return res; + } +#endif +}; + +#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(&storage, v)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(&storage, desired, previous)); + expected = old_val; + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND8(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR8(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR8(&storage, v)); + } +}; + +#elif defined(_M_IX86) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 1u, Signed, Interprocess, core_arch_operations< 1u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock xadd byte ptr [edx], al + mov v, al + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + xchg byte ptr [edx], al + mov v, al + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT + { + base_type::fence_before(success_order); + bool success; + __asm + { + mov esi, expected + mov edi, storage + movzx eax, byte ptr [esi] + movzx edx, desired + lock cmpxchg byte ptr [edi], dl + mov byte ptr [esi], al + sete success + }; + // The success and failure fences are equivalent anyway + base_type::fence_after(success_order); + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + and dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, al + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + or dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, al + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + xor dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, al + }; + base_type::fence_after(order); + return v; + } +}; + +#else + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 1u, Signed > +{ +}; + +#endif + +#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(&storage, v)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(&storage, desired, previous)); + expected = old_val; + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND16(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR16(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR16(&storage, v)); + } +}; + +#elif defined(_M_IX86) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 2u, Signed, Interprocess, core_arch_operations< 2u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock xadd word ptr [edx], ax + mov v, ax + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + xchg word ptr [edx], ax + mov v, ax + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order) BOOST_NOEXCEPT + { + base_type::fence_before(success_order); + bool success; + __asm + { + mov esi, expected + mov edi, storage + movzx eax, word ptr [esi] + movzx edx, desired + lock cmpxchg word ptr [edi], dx + mov word ptr [esi], ax + sete success + }; + // The success and failure fences are equivalent anyway + base_type::fence_after(success_order); + return success; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + and dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, ax + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + or dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, ax + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + xor dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, ax + }; + base_type::fence_after(order); + return v; + } +}; + +#else + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_arch_operations< 4u, Signed, Interprocess >, 2u, Signed > +{ +}; + +#endif + + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG8B) + +template< bool Signed, bool Interprocess > +struct msvc_dcas_x86 +{ + typedef typename storage_traits< 8u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 8u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 8u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + + // Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A, 8.1.1. Guaranteed Atomic Operations: + // + // The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically: + // * Reading or writing a quadword aligned on a 64-bit boundary + // + // Luckily, the memory is almost always 8-byte aligned in our case because atomic<> uses 64 bit native types for storage and dynamic memory allocations + // have at least 8 byte alignment. The only unfortunate case is when atomic is placed on the stack and it is not 8-byte aligned (like on 32 bit Windows). + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + storage_type volatile* p = &storage; + if (BOOST_LIKELY(order != memory_order_seq_cst && ((uintptr_t)p & 7u) == 0u)) + { +#if defined(_M_IX86_FP) && _M_IX86_FP >= 2 +#if defined(__AVX__) + __asm + { + mov edx, p + vmovq xmm4, v + vmovq qword ptr [edx], xmm4 + }; +#else + __asm + { + mov edx, p + movq xmm4, v + movq qword ptr [edx], xmm4 + }; +#endif +#else + __asm + { + mov edx, p + fild v + fistp qword ptr [edx] + }; +#endif + } + else + { + uint32_t backup; + __asm + { + mov backup, ebx + mov edi, p + mov ebx, dword ptr [v] + mov ecx, dword ptr [v + 4] + mov eax, dword ptr [edi] + mov edx, dword ptr [edi + 4] + align 16 + again: + lock cmpxchg8b qword ptr [edi] + jne again + mov ebx, backup + }; + } + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + storage_type const volatile* p = &storage; + storage_type value; + + if (BOOST_LIKELY(((uintptr_t)p & 7u) == 0u)) + { +#if defined(_M_IX86_FP) && _M_IX86_FP >= 2 +#if defined(__AVX__) + __asm + { + mov edx, p + vmovq xmm4, qword ptr [edx] + vmovq value, xmm4 + }; +#else + __asm + { + mov edx, p + movq xmm4, qword ptr [edx] + movq value, xmm4 + }; +#endif +#else + __asm + { + mov edx, p + fild qword ptr [edx] + fistp value + }; +#endif + } + else + { + // We don't care for comparison result here; the previous value will be stored into value anyway. + // Also we don't care for ebx and ecx values, they just have to be equal to eax and edx before cmpxchg8b. + __asm + { + mov edi, p + mov eax, ebx + mov edx, ecx + lock cmpxchg8b qword ptr [edi] + mov dword ptr [value], eax + mov dword ptr [value + 4], edx + }; + } + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + return value; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + // MSVC-11 in 32-bit mode sometimes generates messed up code without compiler barriers, + // even though the _InterlockedCompareExchange64 intrinsic already provides one. + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + storage_type volatile* p = &storage; +#if defined(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64) + const storage_type old_val = (storage_type)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(p, desired, expected); + const bool result = (old_val == expected); + expected = old_val; +#else + bool result; + uint32_t backup; + __asm + { + mov backup, ebx + mov edi, p + mov esi, expected + mov ebx, dword ptr [desired] + mov ecx, dword ptr [desired + 4] + mov eax, dword ptr [esi] + mov edx, dword ptr [esi + 4] + lock cmpxchg8b qword ptr [edi] + mov dword ptr [esi], eax + mov dword ptr [esi + 4], edx + mov ebx, backup + sete result + }; +#endif + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + return result; + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + storage_type volatile* p = &storage; + uint32_t backup; + __asm + { + mov backup, ebx + mov edi, p + mov ebx, dword ptr [v] + mov ecx, dword ptr [v + 4] + mov eax, dword ptr [edi] + mov edx, dword ptr [edi + 4] + align 16 + again: + lock cmpxchg8b qword ptr [edi] + jne again + mov ebx, backup + mov dword ptr [v], eax + mov dword ptr [v + 4], edx + }; + + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + + return v; + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_operations_cas_based< msvc_dcas_x86< Signed, Interprocess > > +{ +}; + +#elif defined(_M_AMD64) + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 8u, Signed, Interprocess > : + public core_arch_operations_msvc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > +{ + typedef core_arch_operations_msvc_x86< 8u, Signed, Interprocess, core_arch_operations< 8u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(&storage, v)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(&storage, desired, previous)); + expected = old_val; + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND64(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR64(&storage, v)); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR64(&storage, v)); + } +}; + +#endif + +#if defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +template< bool Signed, bool Interprocess > +struct msvc_dcas_x86_64 +{ + typedef typename storage_traits< 16u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 16u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 16u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(__AVX__) + if (BOOST_LIKELY(order != memory_order_seq_cst && (((uintptr_t)&storage) & 15u) == 0u)) + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + __m128i value; + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(value)); + _mm_store_si128(const_cast< __m128i* >(reinterpret_cast< volatile __m128i* >(&storage)), value); + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + return; + } +#endif // defined(__AVX__) + + storage_type value = const_cast< storage_type& >(storage); + while (!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, v, &value)) {} + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type value; +#if defined(__AVX__) + if (BOOST_LIKELY((((uintptr_t)&storage) & 15u) == 0u)) + { + __m128i v = _mm_load_si128(const_cast< const __m128i* >(reinterpret_cast< const volatile __m128i* >(&storage))); + BOOST_ATOMIC_DETAIL_MEMCPY(&value, &v, sizeof(value)); + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + return value; + } +#endif // defined(__AVX__) + + value = storage_type(); + BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, value, &value); + return value; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + return !!BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(&storage, desired, &expected); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_arch_operations< 16u, Signed, Interprocess > : + public core_operations_cas_based< cas_based_exchange< msvc_dcas_x86_64< Signed, Interprocess > > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_X86_HAS_CMPXCHG16B) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_operations.hpp b/boost/atomic/detail/core_operations.hpp new file mode 100644 index 0000000..d4bd187 --- /dev/null +++ b/boost/atomic/detail/core_operations.hpp @@ -0,0 +1,49 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_operations.hpp + * + * This header defines core atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_ + +#include +#include +#include +#include + +#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/core_ops_) +#endif + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Default specialization that falls back to architecture-specific implementation +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_operations : + public core_arch_operations< Size, Signed, Interprocess > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_operations_emulated.hpp b/boost/atomic/detail/core_operations_emulated.hpp new file mode 100644 index 0000000..03af21e --- /dev/null +++ b/boost/atomic/detail/core_operations_emulated.hpp @@ -0,0 +1,195 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_operations_emulated.hpp + * + * This header contains lock pool-based implementation of the core atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t Size, std::size_t Alignment, bool = Alignment >= storage_traits< Size >::native_alignment > +struct core_operations_emulated_base +{ + typedef typename storage_traits< Size >::type storage_type; +}; + +template< std::size_t Size, std::size_t Alignment > +struct core_operations_emulated_base< Size, Alignment, false > +{ + typedef buffer_storage< Size, Alignment > storage_type; +}; + +//! Emulated implementation of core atomic operations +template< std::size_t Size, std::size_t Alignment, bool Signed, bool Interprocess > +struct core_operations_emulated : + public core_operations_emulated_base< Size, Alignment > +{ + typedef core_operations_emulated_base< Size, Alignment > base_type; + + // Define storage_type to have alignment not greater than Alignment. This will allow operations to work with value_types + // that possibly have weaker alignment requirements than storage_traits< Size >::type would. This is important for atomic_ref<>. + // atomic<> will allow higher alignment requirement than its value_type. + // Note that storage_type should be an integral type, if possible, so that arithmetic and bitwise operations are possible. + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = Alignment >= storage_traits< Size >::alignment ? storage_traits< Size >::alignment : Alignment; + + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false; + + typedef lock_pool::scoped_lock< storage_alignment > scoped_lock; + + static void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + scoped_lock lock(&storage); + const_cast< storage_type& >(storage) = v; + } + + static storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + scoped_lock lock(&storage); + return const_cast< storage_type const& >(storage); + } + + static storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s += v; + return old_val; + } + + static storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s -= v; + return old_val; + } + + static storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s = v; + return old_val; + } + + static bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + const bool res = old_val == expected; + if (res) + s = desired; + expected = old_val; + + return res; + } + + static bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + // Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call + // is that MSVC-12 ICEs in this case. + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + const bool res = old_val == expected; + if (res) + s = desired; + expected = old_val; + + return res; + } + + static storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s &= v; + return old_val; + } + + static storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s |= v; + return old_val; + } + + static storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s ^= v; + return old_val; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + store(storage, (storage_type)0, order); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_operations_emulated_fwd.hpp b/boost/atomic/detail/core_operations_emulated_fwd.hpp new file mode 100644 index 0000000..d3d9ccf --- /dev/null +++ b/boost/atomic/detail/core_operations_emulated_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_operations_emulated_fwd.hpp + * + * This header forward-declares lock pool-based implementation of the core atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t Size, std::size_t Alignment, bool Signed, bool Interprocess > +struct core_operations_emulated; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_operations_fwd.hpp b/boost/atomic/detail/core_operations_fwd.hpp new file mode 100644 index 0000000..9f2fffa --- /dev/null +++ b/boost/atomic/detail/core_operations_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_operations_fwd.hpp + * + * This header contains forward declaration of the \c core_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_ops_cas_based.hpp b/boost/atomic/detail/core_ops_cas_based.hpp new file mode 100644 index 0000000..0d617e1 --- /dev/null +++ b/boost/atomic/detail/core_ops_cas_based.hpp @@ -0,0 +1,94 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_ops_cas_based.hpp + * + * This header contains CAS-based implementation of core atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct core_operations_cas_based : + public Base +{ + typedef typename Base::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, old_val + v, order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, old_val - v, order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, old_val & v, order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, old_val | v, order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!Base::compare_exchange_weak(storage, old_val, old_val ^ v, order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!Base::exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + Base::store(storage, (storage_type)0, order); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_CAS_BASED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_ops_gcc_atomic.hpp b/boost/atomic/detail/core_ops_gcc_atomic.hpp new file mode 100644 index 0000000..25b4eac --- /dev/null +++ b/boost/atomic/detail/core_ops_gcc_atomic.hpp @@ -0,0 +1,306 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/core_ops_gcc_atomic.hpp + * + * This header contains implementation of the \c core_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE || BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE ||\ + BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE || BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE < BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE +// There are platforms where we need to use larger storage types +#include +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__INTEL_COMPILER) +// This is used to suppress warning #32013 described in gcc_atomic_memory_order_utils.hpp +// for Intel Compiler. +// In debug builds the compiler does not inline any functions, so basically +// every atomic function call results in this warning. I don't know any other +// way to selectively disable just this one warning. +#pragma system_header +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_operations_gcc_atomic +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + + // Note: In the current implementation, core_operations_gcc_atomic are used only when the particularly sized __atomic + // intrinsics are always lock-free (i.e. the corresponding LOCK_FREE macro is 2). Therefore it is safe to + // always set is_always_lock_free to true here. + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_GCC) && BOOST_GCC < 100100 && (defined(__x86_64__) || defined(__i386__)) + // gcc up to 10.1 generates mov + mfence for seq_cst stores, which is slower than xchg + if (order != memory_order_seq_cst) + __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + else + __atomic_exchange_n(&storage, v, __ATOMIC_SEQ_CST); +#else + __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); +#endif + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_RCPC) + // At least gcc 9.3 and clang 10 do not generate relaxed ldapr instructions that are available in ARMv8.3-RCPC extension. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95751 + typedef atomics::detail::core_arch_operations< storage_size, is_signed, is_interprocess > core_arch_operations; + return core_arch_operations::load(storage, order); +#else + return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order)); +#endif + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return __atomic_compare_exchange_n + ( + &storage, &expected, desired, false, + atomics::detail::convert_memory_order_to_gcc(success_order), + atomics::detail::convert_memory_order_to_gcc(failure_order) + ); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return __atomic_compare_exchange_n + ( + &storage, &expected, desired, true, + atomics::detail::convert_memory_order_to_gcc(success_order), + atomics::detail::convert_memory_order_to_gcc(failure_order) + ); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order)); + } +}; + +// We want to only enable __atomic* intrinsics when the corresponding BOOST_ATOMIC_DETAIL_GCC_ATOMIC_*_LOCK_FREE macro indicates +// the same or better lock-free guarantees as the BOOST_ATOMIC_*_LOCK_FREE macro. Otherwise, we want to leave core_operations +// unspecialized, so that core_arch_operations is used instead. + +#if BOOST_ATOMIC_INT128_LOCK_FREE > 0 && BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT128_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 16u, Signed, Interprocess > : + public core_operations_gcc_atomic< 16u, Signed, Interprocess > +{ +}; + +#endif + +#if BOOST_ATOMIC_INT64_LOCK_FREE > 0 +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 8u, Signed, Interprocess > : + public core_operations_gcc_atomic< 8u, Signed, Interprocess > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT64_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 8u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 8u, Signed > +{ +}; + +#endif +#endif // BOOST_ATOMIC_INT64_LOCK_FREE > 0 + + +#if BOOST_ATOMIC_INT32_LOCK_FREE > 0 +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 4u, Signed, Interprocess > : + public core_operations_gcc_atomic< 4u, Signed, Interprocess > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 4u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 4u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT32_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 8u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 4u, Signed > +{ +}; + +#endif +#endif // BOOST_ATOMIC_INT32_LOCK_FREE > 0 + + +#if BOOST_ATOMIC_INT16_LOCK_FREE > 0 +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public core_operations_gcc_atomic< 2u, Signed, Interprocess > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 4u, Signed, Interprocess >, 2u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 2u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT16_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 2u, Signed > +{ +}; + +#endif +#endif // BOOST_ATOMIC_INT16_LOCK_FREE > 0 + + +#if BOOST_ATOMIC_INT8_LOCK_FREE > 0 +#if BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT8_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public core_operations_gcc_atomic< 1u, Signed, Interprocess > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT16_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 2u, Signed, Interprocess >, 1u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT32_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 4u, Signed, Interprocess >, 1u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT64_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 8u, Signed, Interprocess >, 1u, Signed > +{ +}; + +#elif BOOST_ATOMIC_DETAIL_GCC_ATOMIC_INT128_LOCK_FREE >= BOOST_ATOMIC_INT8_LOCK_FREE + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_gcc_atomic< 16u, Signed, Interprocess >, 1u, Signed > +{ +}; + +#endif +#endif // BOOST_ATOMIC_INT8_LOCK_FREE > 0 + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_ATOMIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_ops_gcc_sync.hpp b/boost/atomic/detail/core_ops_gcc_sync.hpp new file mode 100644 index 0000000..34fd5ee --- /dev/null +++ b/boost/atomic/detail/core_ops_gcc_sync.hpp @@ -0,0 +1,263 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_ops_gcc_sync.hpp + * + * This header contains implementation of the \c core_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct core_operations_gcc_sync_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __sync_synchronize(); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + __sync_synchronize(); + } + + static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_acquire) | static_cast< unsigned int >(memory_order_consume))) != 0u) + __sync_synchronize(); + } +}; + +template< std::size_t Size, bool Signed, bool Interprocess > +struct core_operations_gcc_sync : + public core_operations_gcc_sync_base +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< storage_size >::alignment; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + // In general, we cannot guarantee atomicity of plain loads and stores of anything larger than a single byte on + // an arbitrary CPU architecture. However, all modern architectures seem to guarantee atomic loads and stores of + // suitably aligned objects of up to a pointer size. For larger objects we should probably use intrinsics to guarantee + // atomicity. If there appears an architecture where this doesn't hold, this threshold needs to be updated (patches are welcome). + typedef atomics::detail::integral_constant< bool, storage_size <= sizeof(void*) > plain_stores_loads_are_atomic; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + store(storage, v, order, plain_stores_loads_are_atomic()); + } + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order, atomics::detail::true_type) BOOST_NOEXCEPT + { + fence_before_store(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order, atomics::detail::false_type) BOOST_NOEXCEPT + { + exchange(storage, v, order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return load(storage, order, plain_stores_loads_are_atomic()); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order, atomics::detail::true_type) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order, atomics::detail::false_type) BOOST_NOEXCEPT + { + // Note: don't use fetch_add or other arithmetics here since storage_type may not be an arithmetic type. + storage_type expected = storage_type(); + storage_type desired = expected; + // We don't care if CAS succeeds or not. If it does, it will just write the same value there was before. + return __sync_val_compare_and_swap(const_cast< storage_type volatile* >(&storage), expected, desired); + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return __sync_fetch_and_add(&storage, v); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return __sync_fetch_and_sub(&storage, v); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + // GCC docs mention that not all architectures may support full exchange semantics for this intrinsic. However, GCC's implementation of + // std::atomic<> uses this intrinsic unconditionally. We do so as well. In case if some architectures actually don't support this, we can always + // add a check here and fall back to a CAS loop. + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __sync_synchronize(); + return __sync_lock_test_and_set(&storage, v); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + storage_type expected2 = expected; + storage_type old_val = __sync_val_compare_and_swap(&storage, expected2, desired); + + if (old_val == expected2) + { + return true; + } + else + { + expected = old_val; + return false; + } + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return __sync_fetch_and_and(&storage, v); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return __sync_fetch_and_or(&storage, v); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + return __sync_fetch_and_xor(&storage, v); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __sync_synchronize(); + return !!__sync_lock_test_and_set(&storage, 1); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + __sync_lock_release(&storage); + if (order == memory_order_seq_cst) + __sync_synchronize(); + } +}; + +#if BOOST_ATOMIC_INT8_LOCK_FREE > 0 +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) + public core_operations_gcc_sync< 1u, Signed, Interprocess > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 2u, Signed, Interprocess >, 1u, Signed > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 4u, Signed, Interprocess >, 1u, Signed > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 1u, Signed > +#else + public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 1u, Signed > +#endif +{ +}; +#endif + +#if BOOST_ATOMIC_INT16_LOCK_FREE > 0 +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) + public core_operations_gcc_sync< 2u, Signed, Interprocess > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 4u, Signed, Interprocess >, 2u, Signed > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 2u, Signed > +#else + public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 2u, Signed > +#endif +{ +}; +#endif + +#if BOOST_ATOMIC_INT32_LOCK_FREE > 0 +template< bool Signed, bool Interprocess > +struct core_operations< 4u, Signed, Interprocess > : +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) + public core_operations_gcc_sync< 4u, Signed, Interprocess > +#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) + public extending_cas_based_arithmetic< core_operations_gcc_sync< 8u, Signed, Interprocess >, 4u, Signed > +#else + public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 4u, Signed > +#endif +{ +}; +#endif + +#if BOOST_ATOMIC_INT64_LOCK_FREE > 0 +template< bool Signed, bool Interprocess > +struct core_operations< 8u, Signed, Interprocess > : +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) + public core_operations_gcc_sync< 8u, Signed, Interprocess > +#else + public extending_cas_based_arithmetic< core_operations_gcc_sync< 16u, Signed, Interprocess >, 8u, Signed > +#endif +{ +}; +#endif + +#if BOOST_ATOMIC_INT128_LOCK_FREE > 0 +template< bool Signed, bool Interprocess > +struct core_operations< 16u, Signed, Interprocess > : + public core_operations_gcc_sync< 16u, Signed, Interprocess > +{ +}; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_GCC_SYNC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_ops_linux_arm.hpp b/boost/atomic/detail/core_ops_linux_arm.hpp new file mode 100644 index 0000000..f00cde2 --- /dev/null +++ b/boost/atomic/detail/core_ops_linux_arm.hpp @@ -0,0 +1,169 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009, 2011 Helge Bahmann + * Copyright (c) 2009 Phil Endecott + * Copyright (c) 2013 Tim Blechmann + * Linux-specific code by Phil Endecott + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_ops_linux_arm.hpp + * + * This header contains implementation of the \c core_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +// Different ARM processors have different atomic instructions. In particular, +// architecture versions before v6 (which are still in widespread use, e.g. the +// Intel/Marvell XScale chips like the one in the NSLU2) have only atomic swap. +// On Linux the kernel provides some support that lets us abstract away from +// these differences: it provides emulated CAS and barrier functions at special +// addresses that are guaranteed not to be interrupted by the kernel. Using +// this facility is slightly slower than inline assembler would be, but much +// faster than a system call. +// +// https://lwn.net/Articles/314561/ +// +// While this emulated CAS is "strong" in the sense that it does not fail +// "spuriously" (i.e.: it never fails to perform the exchange when the value +// found equals the value expected), it does not return the found value on +// failure. To satisfy the atomic API, compare_exchange_{weak|strong} must +// return the found value on failure, and we have to manually load this value +// after the emulated CAS reports failure. This in turn introduces a race +// between the CAS failing (due to the "wrong" value being found) and subsequently +// loading (which might turn up the "right" value). From an application's +// point of view this looks like "spurious failure", and therefore the +// emulated CAS is only good enough to provide compare_exchange_weak +// semantics. + +struct linux_arm_cas_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = true; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before_store(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + fence_operations::hardware_full_fence(); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + fence_operations::hardware_full_fence(); + } + + static BOOST_FORCEINLINE void fence_after_load(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + fence_operations::hardware_full_fence(); + } +}; + +template< bool Signed, bool Interprocess > +struct linux_arm_cas : + public linux_arm_cas_base +{ + typedef typename storage_traits< 4u >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = 4u; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = 4u; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + fence_before_store(order); + storage = v; + fence_after_store(order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type v = storage; + fence_after_load(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + while (true) + { + storage_type tmp = expected; + if (compare_exchange_weak(storage, tmp, desired, success_order, failure_order)) + return true; + if (tmp != expected) + { + expected = tmp; + return false; + } + } + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT + { + typedef storage_type (*kernel_cmpxchg32_t)(storage_type oldval, storage_type newval, volatile storage_type* ptr); + + if (((kernel_cmpxchg32_t)0xffff0fc0)(expected, desired, &storage) == 0) + { + return true; + } + else + { + expected = storage; + return false; + } + } +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 1u, Signed > +{ +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > >, 2u, Signed > +{ +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 4u, Signed, Interprocess > : + public core_operations_cas_based< cas_based_exchange< linux_arm_cas< Signed, Interprocess > > > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_LINUX_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/core_ops_windows.hpp b/boost/atomic/detail/core_ops_windows.hpp new file mode 100644 index 0000000..346c334 --- /dev/null +++ b/boost/atomic/detail/core_ops_windows.hpp @@ -0,0 +1,201 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/core_ops_windows.hpp + * + * This header contains implementation of the \c core_operations template. + * + * This implementation is the most basic version for Windows. It should + * work for any non-MSVC-like compilers as long as there are Interlocked WinAPI + * functions available. This version is also used for WinCE. + * + * Notably, this implementation is not as efficient as other + * versions based on compiler intrinsics. + */ + +#ifndef BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct core_operations_windows_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void fence_after(memory_order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } +}; + +template< std::size_t Size, bool Signed, bool Interprocess, typename Derived > +struct core_operations_windows : + public core_operations_windows_base +{ + typedef typename storage_traits< Size >::type storage_type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; + static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = storage_traits< Size >::alignment; + static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; + static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + Derived::exchange(storage, v, order); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return Derived::fetch_add(const_cast< storage_type volatile& >(storage), (storage_type)0, order); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + typedef typename boost::atomics::detail::make_signed< storage_type >::type signed_storage_type; + return Derived::fetch_add(storage, static_cast< storage_type >(-static_cast< signed_storage_type >(v)), order); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return Derived::compare_exchange_strong(storage, expected, desired, success_order, failure_order); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!Derived::exchange(storage, (storage_type)1, order); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + store(storage, (storage_type)0, order); + } +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 4u, Signed, bool Interprocess > : + public core_operations_windows< 4u, Signed, Interprocess, core_operations< 4u, Signed, Interprocess > > +{ + typedef core_operations_windows< 4u, Signed, Interprocess, core_operations< 4u, Signed, Interprocess > > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(&storage, v)); + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_EXCHANGE(&storage, v)); + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + storage_type previous = expected; + base_type::fence_before(success_order); + storage_type old_val = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(&storage, desired, previous)); + expected = old_val; + // The success and failure fences are the same anyway + base_type::fence_after(success_order); + return (previous == old_val); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_INTERLOCKED_AND) + base_type::fence_before(order); + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_AND(&storage, v)); + base_type::fence_after(order); + return v; +#else + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res & v, order, memory_order_relaxed)) {} + return res; +#endif + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_INTERLOCKED_OR) + base_type::fence_before(order); + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_OR(&storage, v)); + base_type::fence_after(order); + return v; +#else + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res | v, order, memory_order_relaxed)) {} + return res; +#endif + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_INTERLOCKED_XOR) + base_type::fence_before(order); + v = static_cast< storage_type >(BOOST_ATOMIC_INTERLOCKED_XOR(&storage, v)); + base_type::fence_after(order); + return v; +#else + storage_type res = storage; + while (!compare_exchange_strong(storage, res, res ^ v, order, memory_order_relaxed)) {} + return res; +#endif + } +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 1u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations< 4u, Signed, Interprocess >, 1u, Signed > +{ +}; + +template< bool Signed, bool Interprocess > +struct core_operations< 2u, Signed, Interprocess > : + public extending_cas_based_arithmetic< core_operations< 4u, Signed, Interprocess >, 2u, Signed > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_CORE_OPS_WINDOWS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extending_cas_based_arithmetic.hpp b/boost/atomic/detail/extending_cas_based_arithmetic.hpp new file mode 100644 index 0000000..7b8d4c3 --- /dev/null +++ b/boost/atomic/detail/extending_cas_based_arithmetic.hpp @@ -0,0 +1,72 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/extending_cas_based_arithmetic.hpp + * + * This header contains a boilerplate of core atomic operations that require sign/zero extension in arithmetic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, std::size_t Size, bool Signed > +struct extending_cas_based_arithmetic : + public Base +{ + typedef typename Base::storage_type storage_type; + typedef typename storage_traits< Size >::type emulated_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + storage_type new_val; + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v)); + } + while (!Base::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return old_val; + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + storage_type new_val; + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v)); + } + while (!Base::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return old_val; + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTENDING_CAS_BASED_ARITHMETIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_fp_operations.hpp b/boost/atomic/detail/extra_fp_operations.hpp new file mode 100644 index 0000000..854d8c9 --- /dev/null +++ b/boost/atomic/detail/extra_fp_operations.hpp @@ -0,0 +1,28 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_fp_operations.hpp + * + * This header defines extra floating point atomic operations, including the generic version. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_GENERIC) +#include BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_HEADER(boost/atomic/detail/extra_fp_ops_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_fp_operations_fwd.hpp b/boost/atomic/detail/extra_fp_operations_fwd.hpp new file mode 100644 index 0000000..07ca1ac --- /dev/null +++ b/boost/atomic/detail/extra_fp_operations_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_fp_operations_fwd.hpp + * + * This header contains forward declaration of the \c extra_fp_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, typename Value = typename Base::value_type, std::size_t Size = sizeof(typename Base::storage_type), bool = Base::is_always_lock_free > +struct extra_fp_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_fp_ops_emulated.hpp b/boost/atomic/detail/extra_fp_ops_emulated.hpp new file mode 100644 index 0000000..df55675 --- /dev/null +++ b/boost/atomic/detail/extra_fp_ops_emulated.hpp @@ -0,0 +1,118 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_fp_ops_emulated.hpp + * + * This header contains emulated (lock-based) implementation of the extra floating point atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Emulated implementation of extra floating point operations +template< typename Base, typename Value, std::size_t Size > +struct extra_fp_operations_emulated : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + typedef typename base_type::scoped_lock scoped_lock; + + static value_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = -old_val; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return old_val; + } + + static value_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = -old_val; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return new_val; + } + + static value_type add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = old_val + v; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return new_val; + } + + static value_type sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = old_val - v; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return new_val; + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_sub(storage, v, order); + } +}; + +template< typename Base, typename Value, std::size_t Size > +struct extra_fp_operations< Base, Value, Size, false > : + public extra_fp_operations_emulated< Base, Value, Size > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_fp_ops_generic.hpp b/boost/atomic/detail/extra_fp_ops_generic.hpp new file mode 100644 index 0000000..aefd7d3 --- /dev/null +++ b/boost/atomic/detail/extra_fp_ops_generic.hpp @@ -0,0 +1,192 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_fp_ops_generic.hpp + * + * This header contains generic implementation of the extra floating point atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_GCC) && BOOST_GCC >= 60000 +#pragma GCC diagnostic push +// ignoring attributes on template argument X - this warning is because we need to pass storage_type as a template argument; no problem in this case +#pragma GCC diagnostic ignored "-Wignored-attributes" +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Negate implementation +template< + typename Base, + typename Value, + std::size_t Size +#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH) + , bool = atomics::detail::is_iec559< Value >::value && atomics::detail::is_integral< typename Base::storage_type >::value +#endif +> +struct extra_fp_negate_generic : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + + static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = -old_val; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return old_val; + } + + static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = -old_val; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + fetch_negate(storage, order); + } +}; + +#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH) + +//! Negate implementation for IEEE 754 / IEC 559 floating point types. We leverage the fact that the sign bit is the most significant bit in the value. +template< typename Base, typename Value, std::size_t Size > +struct extra_fp_negate_generic< Base, Value, Size, true > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + + //! The mask with only one sign bit set to 1 + static BOOST_CONSTEXPR_OR_CONST storage_type sign_mask = static_cast< storage_type >(1u) << (atomics::detail::value_size_of< value_type >::value * 8u - 1u); + + static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return atomics::detail::bitwise_fp_cast< value_type >(base_type::fetch_xor(storage, sign_mask, order)); + } + + static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return atomics::detail::bitwise_fp_cast< value_type >(base_type::bitwise_xor(storage, sign_mask, order)); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::opaque_xor(storage, sign_mask, order); + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH) + +//! Generic implementation of floating point operations +template< typename Base, typename Value, std::size_t Size > +struct extra_fp_operations_generic : + public extra_fp_negate_generic< Base, Value, Size > +{ + typedef extra_fp_negate_generic< Base, Value, Size > base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + + static BOOST_FORCEINLINE value_type add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = old_val + v; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE value_type sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = old_val - v; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_sub(storage, v, order); + } +}; + +// Default extra_fp_operations template definition will be used unless specialized for a specific platform +template< typename Base, typename Value, std::size_t Size > +struct extra_fp_operations< Base, Value, Size, true > : + public extra_fp_operations_generic< Base, Value, Size > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#if defined(BOOST_GCC) && BOOST_GCC >= 60000 +#pragma GCC diagnostic pop +#endif + +#include + +#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_operations.hpp b/boost/atomic/detail/extra_operations.hpp new file mode 100644 index 0000000..c04f55c --- /dev/null +++ b/boost/atomic/detail/extra_operations.hpp @@ -0,0 +1,28 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_operations.hpp + * + * This header defines extra atomic operations, including the generic version. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_GENERIC) +#include BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_HEADER(boost/atomic/detail/extra_ops_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_operations_fwd.hpp b/boost/atomic/detail/extra_operations_fwd.hpp new file mode 100644 index 0000000..15be025 --- /dev/null +++ b/boost/atomic/detail/extra_operations_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_operations_fwd.hpp + * + * This header contains forward declaration of the \c extra_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, std::size_t Size = sizeof(typename Base::storage_type), bool Signed = Base::is_signed, bool = Base::is_always_lock_free > +struct extra_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_emulated.hpp b/boost/atomic/detail/extra_ops_emulated.hpp new file mode 100644 index 0000000..1de9a66 --- /dev/null +++ b/boost/atomic/detail/extra_ops_emulated.hpp @@ -0,0 +1,258 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_emulated.hpp + * + * This header contains emulated (lock-based) implementation of the extra atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Emulated implementation of extra operations +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_emulated : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::scoped_lock scoped_lock; + + static storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s = static_cast< storage_type >(-old_val); + return old_val; + } + + static storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = static_cast< storage_type >(-s); + s = new_val; + return new_val; + } + + static storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = s; + new_val += v; + s = new_val; + return new_val; + } + + static storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = s; + new_val -= v; + s = new_val; + return new_val; + } + + static storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = s; + new_val &= v; + s = new_val; + return new_val; + } + + static storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = s; + new_val |= v; + s = new_val; + return new_val; + } + + static storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = s; + new_val ^= v; + s = new_val; + return new_val; + } + + static storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type old_val = s; + s = static_cast< storage_type >(~old_val); + return old_val; + } + + static storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + storage_type new_val = static_cast< storage_type >(~s); + s = new_val; + return new_val; + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_sub(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_and(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_or(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + base_type::fetch_xor(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + fetch_complement(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!add(storage, v, order); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!sub(storage, v, order); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + return !!bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); + storage_type old_val = base_type::fetch_or(storage, mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); + storage_type old_val = base_type::fetch_and(storage, ~mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); + storage_type old_val = base_type::fetch_xor(storage, mask, order); + return !!(old_val & mask); + } +}; + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations< Base, Size, Signed, false > : + public extra_operations_emulated< Base, Size, Signed > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_gcc_aarch32.hpp b/boost/atomic/detail/extra_ops_gcc_aarch32.hpp new file mode 100644 index 0000000..7e9af37 --- /dev/null +++ b/boost/atomic/detail/extra_ops_gcc_aarch32.hpp @@ -0,0 +1,1060 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_gcc_aarch32.hpp + * + * This header contains implementation of the extra atomic operations for AArch32. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct extra_operations_gcc_aarch32_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + // Note: For opaque operations prefer operations returning the resulting values instead of the original values + // as these operations require less registers. + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_complement(storage, order); + } +}; + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_gcc_aarch32; + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch32< Base, 1u, Signed > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "rsb %[result], %[original], #0\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "rsb %[result], #0\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "add %[result], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "sub %[result], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "and %[result], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "orr %[result], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "eor %[result], %[value]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[original], %[storage]\n\t"\ + "mvn %[result], %[original]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exb %[result], %[storage]\n\t"\ + "mvn %[result], %[result]\n\t"\ + "st" st_mo "exb %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 1u, Signed > > +{ +}; + + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch32< Base, 2u, Signed > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "rsb %[result], %[original], #0\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "rsb %[result], #0\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "add %[result], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "sub %[result], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "and %[result], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "orr %[result], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "eor %[result], %[value]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[original], %[storage]\n\t"\ + "mvn %[result], %[original]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exh %[result], %[storage]\n\t"\ + "mvn %[result], %[result]\n\t"\ + "st" st_mo "exh %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 2u, Signed, true > : + public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 2u, Signed > > +{ +}; + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch32< Base, 4u, Signed > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "rsb %[result], %[original], #0\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "rsb %[result], #0\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "add %[result], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "sub %[result], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "and %[result], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "orr %[result], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "eor %[result], %[value]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : [value] "Ir" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[original], %[storage]\n\t"\ + "mvn %[result], %[original]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [original] "=&r" (original), [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "ex %[result], %[storage]\n\t"\ + "mvn %[result], %[result]\n\t"\ + "st" st_mo "ex %[tmp], %[result], %[storage]\n\t"\ + "teq %[tmp], #0\n\t"\ + "bne 1b\n\t"\ + : [result] "=&r" (result), [tmp] "=&r" (tmp), [storage] "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 4u, Signed > > +{ +}; + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch32< Base, 8u, Signed > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "mvn %3, %0\n\t"\ + "mvn %H3, %H0\n\t"\ + "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) ", #1\n\t"\ + "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) ", #0\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "mvn %0, %0\n\t"\ + "mvn %H0, %H0\n\t"\ + "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", #1\n\t"\ + "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", #0\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "adds " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) "\n\t"\ + "adc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) "\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "subs " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(3) "\n\t"\ + "sbc " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(0) ", " BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(3) "\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "and %0, %3\n\t"\ + "and %H0, %H3\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "orr %0, %3\n\t"\ + "orr %H0, %H3\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "eor %0, %3\n\t"\ + "eor %H0, %H3\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : "r" (v)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "mvn %3, %0\n\t"\ + "mvn %H3, %H0\n\t"\ + "st" st_mo "exd %1, %3, %H3, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (original), "=&r" (tmp), "+Q" (storage), "=&r" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "exd %0, %H0, %2\n\t"\ + "mvn %0, %0\n\t"\ + "mvn %H0, %H0\n\t"\ + "st" st_mo "exd %1, %0, %H0, %2\n\t"\ + "teq %1, #0\n\t"\ + "bne 1b\n\t"\ + : "=&r" (result), "=&r" (tmp), "+Q" (storage)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN + + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_gcc_aarch32_common< extra_operations_gcc_aarch32< Base, 8u, Signed > > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH32_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_gcc_aarch64.hpp b/boost/atomic/detail/extra_ops_gcc_aarch64.hpp new file mode 100644 index 0000000..922d810 --- /dev/null +++ b/boost/atomic/detail/extra_ops_gcc_aarch64.hpp @@ -0,0 +1,1330 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_gcc_aarch64.hpp + * + * This header contains implementation of the extra atomic operations for AArch64. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH64_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH64_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct extra_operations_gcc_aarch64_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + // Note: For opaque operations prefer operations returning the resulting values instead of the original values + // as these operations require less registers. That is unless LSE is available, in which case + // it is better to use the dedicated atomic instructions. The LSE check is done in the base_type, + // where needed (e.g. for 128-bit operations there are no LSE instructions). + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_complement(storage, order); + } +}; + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_gcc_aarch64; + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch64< Base, 1u, Signed > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "neg %w[result], %w[original]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "neg %w[result], %w[result]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#if !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "add %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "sub %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "and %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "orr %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "eor %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[original], %[storage]\n\t"\ + "mvn %w[result], %w[original]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrb %w[result], %[storage]\n\t"\ + "mvn %w[result], %w[result]\n\t"\ + "st" st_mo "xrb %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#endif // !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_gcc_aarch64_common< extra_operations_gcc_aarch64< Base, 1u, Signed > > +{ +}; + + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch64< Base, 2u, Signed > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "neg %w[result], %w[original]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "neg %w[result], %w[result]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#if !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "add %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "sub %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "and %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "orr %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "eor %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[original], %[storage]\n\t"\ + "mvn %w[result], %w[original]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xrh %w[result], %[storage]\n\t"\ + "mvn %w[result], %w[result]\n\t"\ + "st" st_mo "xrh %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#endif // !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 2u, Signed, true > : + public extra_operations_gcc_aarch64_common< extra_operations_gcc_aarch64< Base, 2u, Signed > > +{ +}; + + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch64< Base, 4u, Signed > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "neg %w[result], %w[original]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "neg %w[result], %w[result]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#if !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "add %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "sub %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "and %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "orr %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "eor %w[result], %w[result], %w[value]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Kr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[original], %[storage]\n\t"\ + "mvn %w[result], %w[original]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %w[result], %[storage]\n\t"\ + "mvn %w[result], %w[result]\n\t"\ + "st" st_mo "xr %w[tmp], %w[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#endif // !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_gcc_aarch64_common< extra_operations_gcc_aarch64< Base, 4u, Signed > > +{ +}; + + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch64< Base, 8u, Signed > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "neg %x[result], %x[original]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "neg %x[result], %x[result]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#if !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "add %x[result], %x[result], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "sub %x[result], %x[result], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Ir" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "and %x[result], %x[result], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Lr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "orr %x[result], %x[result], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Lr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "eor %x[result], %x[result], %x[value]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : [value] "Lr" (v)\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[original], %[storage]\n\t"\ + "mvn %x[result], %x[original]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [result] "=&r" (result), [storage] "+Q" (storage), [original] "=&r" (original)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xr %x[result], %[storage]\n\t"\ + "mvn %x[result], %x[result]\n\t"\ + "st" st_mo "xr %w[tmp], %x[result], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage), [result] "=&r" (result)\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result; + } + +#endif // !defined(BOOST_ATOMIC_DETAIL_AARCH64_HAS_LSE) +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_gcc_aarch64_common< extra_operations_gcc_aarch64< Base, 8u, Signed > > +{ +}; + + +template< typename Base, bool Signed > +struct extra_operations_gcc_aarch64< Base, 16u, Signed > : + public extra_operations_generic< Base, 16u, Signed > +{ + typedef extra_operations_generic< Base, 16u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename base_type::storage_union storage_union; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "mvn %x[result_0], %x[original_0]\n\t"\ + "mvn %x[result_1], %x[original_1]\n\t"\ + "adds %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], #1\n\t"\ + "adc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], xzr\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "mvn %x[result_0], %x[result_0]\n\t"\ + "mvn %x[result_1], %x[result_1]\n\t"\ + "adds %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], #1\n\t"\ + "adc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], xzr\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "adds %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "]\n\t"\ + "adc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "r" (value.as_uint64[0u]), [value_1] "r" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "subs %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "]\n\t"\ + "sbc %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[result_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "], %x[value_" BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "r" (value.as_uint64[0u]), [value_1] "r" (value.as_uint64[1u])\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "and %x[result_0], %x[result_0], %x[value_0]\n\t"\ + "and %x[result_1], %x[result_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "orr %x[result_0], %x[result_0], %x[value_0]\n\t"\ + "orr %x[result_1], %x[result_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + storage_union value = { v }; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "eor %x[result_0], %x[result_0], %x[value_0]\n\t"\ + "eor %x[result_1], %x[result_1], %x[value_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : [value_0] "Lr" (value.as_uint64[0u]), [value_1] "Lr" (value.as_uint64[1u])\ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_union original; + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[original_0], %x[original_1], %[storage]\n\t"\ + "mvn %x[result_0], %x[original_0]\n\t"\ + "mvn %x[result_1], %x[original_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [original_0] "=&r" (original.as_uint64[0u]), [original_1] "=&r" (original.as_uint64[1u]),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return original.as_storage; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_union result; + uint32_t tmp; + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN(ld_mo, st_mo)\ + __asm__ __volatile__\ + (\ + "1:\n\t"\ + "ld" ld_mo "xp %x[result_0], %x[result_1], %[storage]\n\t"\ + "mvn %x[result_0], %x[result_0]\n\t"\ + "mvn %x[result_1], %x[result_1]\n\t"\ + "st" st_mo "xp %w[tmp], %x[result_0], %x[result_1], %[storage]\n\t"\ + "cbnz %w[tmp], 1b\n\t"\ + : [tmp] "=&r" (tmp), [storage] "+Q" (storage),\ + [result_0] "=&r" (result.as_uint64[0u]), [result_1] "=&r" (result.as_uint64[1u])\ + : \ + : "memory"\ + ); + + BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(order) +#undef BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN + + return result.as_storage; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 16u, Signed, true > : + public extra_operations_gcc_aarch64_common< extra_operations_gcc_aarch64< Base, 16u, Signed > > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_AARCH64_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_gcc_arm.hpp b/boost/atomic/detail/extra_ops_gcc_arm.hpp new file mode 100644 index 0000000..3577b8a --- /dev/null +++ b/boost/atomic/detail/extra_ops_gcc_arm.hpp @@ -0,0 +1,1119 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 - 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_gcc_arm.hpp + * + * This header contains implementation of the extra atomic operations for ARM. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct extra_operations_gcc_arm_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_complement(storage, order); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_complement(storage, order); + } +}; + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_gcc_arm; + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) + +template< typename Base, bool Signed > +struct extra_operations_gcc_arm< Base, 1u, Signed > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type extended_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "mvn %[result], %[original]\n\t" // result = NOT original + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexb %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "mvn %[result], %[original]\n\t" // result = NOT original + "strexb %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_gcc_arm_common< extra_operations_gcc_arm< Base, 1u, Signed > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXB_STREXB) + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) + +template< typename Base, bool Signed > +struct extra_operations_gcc_arm< Base, 2u, Signed > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type extended_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "mvn %[result], %[original]\n\t" // result = NOT original + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(original); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + extended_storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrexh %[original], %[storage]\n\t" // original = zero_extend(*(&storage)) + "mvn %[result], %[original]\n\t" // result = NOT original + "strexh %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return static_cast< storage_type >(result); + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 2u, Signed, true > : + public extra_operations_gcc_arm_common< extra_operations_gcc_arm< Base, 2u, Signed > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXH_STREXH) + +template< typename Base, bool Signed > +struct extra_operations_gcc_arm< Base, 4u, Signed > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "rsb %[result], %[original], #0\n\t" // result = 0 - original + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "add %[result], %[original], %[value]\n\t" // result = original + value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "sub %[result], %[original], %[value]\n\t" // result = original - value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "and %[result], %[original], %[value]\n\t" // result = original & value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "orr %[result], %[original], %[value]\n\t" // result = original | value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "eor %[result], %[original], %[value]\n\t" // result = original ^ value + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : [value] "Ir" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "mvn %[result], %[original]\n\t" // result = NOT original + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + uint32_t tmp; + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%[tmp]) + "1:\n\t" + "ldrex %[original], %[storage]\n\t" // original = *(&storage) + "mvn %[result], %[original]\n\t" // result = NOT original + "strex %[tmp], %[result], %[storage]\n\t" // *(&storage) = result, tmp = store failed + "teq %[tmp], #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%[tmp]) + : [original] "=&r" (original), // %0 + [result] "=&r" (result), // %1 + [tmp] "=&l" (tmp), // %2 + [storage] "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_gcc_arm_common< extra_operations_gcc_arm< Base, 4u, Signed > > +{ +}; + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) + +template< typename Base, bool Signed > +struct extra_operations_gcc_arm< Base, 8u, Signed > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "mvn %2, %1\n\t" // result = NOT original + "mvn %H2, %H1\n\t" + "adds " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", #1\n\t" // result = result + 1 + "adc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", #0\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "mvn %2, %1\n\t" // result = NOT original + "mvn %H2, %H1\n\t" + "adds " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", #1\n\t" // result = result + 1 + "adc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", #0\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "adds " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t" // result = original + value + "adc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "subs " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(4) "\n\t" // result = original - value + "sbc " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(2) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(1) ", " BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(4) "\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "and %2, %1, %4\n\t" // result = original & value + "and %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "orr %2, %1, %4\n\t" // result = original | value + "orr %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "eor %2, %1, %4\n\t" // result = original ^ value + "eor %H2, %H1, %H4\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : "r" (v) // %4 + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "mvn %2, %1\n\t" // result = NOT original + "mvn %H2, %H1\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_arm_base::fence_before(order); + storage_type original, result; + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "1:\n\t" + "ldrexd %1, %H1, %3\n\t" // original = *(&storage) + "mvn %2, %1\n\t" // result = NOT original + "mvn %H2, %H1\n\t" + "strexd %0, %2, %H2, %3\n\t" // *(&storage) = result, tmp = store failed + "teq %0, #0\n\t" // flags = tmp==0 + "bne 1b\n\t" // if (!flags.equal) goto retry + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(tmp), // %0 + "=&r" (original), // %1 + "=&r" (result), // %2 + "+Q" (storage) // %3 + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_arm_base::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_gcc_arm_common< extra_operations_gcc_arm< Base, 8u, Signed > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_ARM_HAS_LDREXD_STREXD) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_gcc_ppc.hpp b/boost/atomic/detail/extra_ops_gcc_ppc.hpp new file mode 100644 index 0000000..476c60e --- /dev/null +++ b/boost/atomic/detail/extra_ops_gcc_ppc.hpp @@ -0,0 +1,844 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 - 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_gcc_ppc.hpp + * + * This header contains implementation of the extra atomic operations for PowerPC. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_PPC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct extra_operations_gcc_ppc_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_complement(storage, order); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::negate(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::add(storage, v, order); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::sub(storage, v, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!base_type::bitwise_complement(storage, order); + } +}; + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_gcc_ppc; + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) + +template< typename Base, bool Signed > +struct extra_operations_gcc_ppc< Base, 1u, Signed > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lbarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stbcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 1u, Signed > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LBARX_STBCX) + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) + +template< typename Base, bool Signed > +struct extra_operations_gcc_ppc< Base, 2u, Signed > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "neg %1,%0\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "neg %1,%0\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lharx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "sthcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LHARX_STHCX) + +template< typename Base, bool Signed > +struct extra_operations_gcc_ppc< Base, 4u, Signed > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "lwarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stwcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 4u, Signed > > +{ +}; + +#if defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) + +template< typename Base, bool Signed > +struct extra_operations_gcc_ppc< Base, 8u, Signed > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "neg %1,%0\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "add %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "sub %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "and %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "or %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type original, result; + core_arch_operations_gcc_ppc_base::fence_before(order); + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "xor %1,%0,%3\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : "b" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return original; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + core_arch_operations_gcc_ppc_base::fence_before(order); + storage_type original, result; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL("1") + "ldarx %0,%y2\n\t" + "nor %1,%0,%0\n\t" + "stdcx. %1,%y2\n\t" + BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP("bne-", "1b", "-12") + : "=&b" (original), "=&b" (result), "+Z" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC + ); + core_arch_operations_gcc_ppc_base::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_gcc_ppc_common< extra_operations_gcc_ppc< Base, 8u, Signed > > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_PPC_HAS_LDARX_STDCX) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_ARM_PPC_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_gcc_x86.hpp b/boost/atomic/detail/extra_ops_gcc_x86.hpp new file mode 100644 index 0000000..a2bdec2 --- /dev/null +++ b/boost/atomic/detail/extra_ops_gcc_x86.hpp @@ -0,0 +1,1786 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2015 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_gcc_x86.hpp + * + * This header contains implementation of the extra atomic operations for x86. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_X86_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type temp_storage_type; + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: movzbl %[orig], %2\n\t"\ + op " %b2\n\t"\ + "lock; cmpxchgb %b2, %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), "=&q" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negb", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notb", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negb", original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notb", original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %2\n\t"\ + op " %%al, %b2\n\t"\ + "lock; cmpxchgb %b2, %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), "=&q" (result)\ + : [arg] "ir" ((temp_storage_type)argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andb", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orb", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorb", v, original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incb %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addb %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decb %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subb %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; negb %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; andb %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; orb %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xorb %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; notb %[storage]\n\t" + : [storage] "+m" (storage) + : + : "memory" + ); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incb %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addb %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incb %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addb %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decb %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subb %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decb %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subb %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; andb %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; andb %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; orb %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; orb %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; xorb %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; xorb %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 2u, Signed, true > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< 4u >::type temp_storage_type; + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: movzwl %[orig], %2\n\t"\ + op " %w2\n\t"\ + "lock; cmpxchgw %w2, %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), "=&q" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negw", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notw", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negw", original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notw", original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %2\n\t"\ + op " %%ax, %w2\n\t"\ + "lock; cmpxchgw %w2, %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), "=&q" (result)\ + : [arg] "ir" ((temp_storage_type)argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andw", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orw", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + temp_storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorw", v, original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incw %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addw %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decw %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subw %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; negw %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; andw %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; orw %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xorw %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; notw %[storage]\n\t" + : [storage] "+m" (storage) + : + : "memory" + ); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incw %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addw %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incw %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addw %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decw %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subw %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decw %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subw %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; andw %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; andw %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; orw %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; orw %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; xorw %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "iq" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; xorw %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "iq" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btsw %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btsw %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btrw %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btrw %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btcw %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btcw %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kq" ((uint16_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[orig], %[res]\n\t"\ + op " %[res]\n\t"\ + "lock; cmpxchgl %[res], %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), [res] "=&r" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negl", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notl", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negl", original, result); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notl", original, result); + return result; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %[res]\n\t"\ + op " %%eax, %[res]\n\t"\ + "lock; cmpxchgl %[res], %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), [res] "=&r" (result)\ + : [arg] "ir" (argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andl", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orl", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorl", v, original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incl %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addl %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decl %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subl %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; negl %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; andl %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; orl %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xorl %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; notl %[storage]\n\t" + : [storage] "+m" (storage) + : + : "memory" + ); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incl %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addl %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "ir" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incl %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addl %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decl %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subl %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "ir" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decl %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subl %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; andl %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "ir" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; andl %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; orl %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "ir" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; orl %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; xorl %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "ir" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; xorl %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "ir" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btsl %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btsl %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btrl %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btrl %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btcl %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btcl %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint32_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } +}; + +#if defined(__x86_64__) + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[orig], %[res]\n\t"\ + op " %[res]\n\t"\ + "lock; cmpxchgq %[res], %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), [res] "=&r" (result)\ + : \ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negq", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notq", original, result); + return original; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("negq", original, result); + return result; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("notq", original, result); + return result; + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + +#define BOOST_ATOMIC_DETAIL_CAS_LOOP(op, argument, original, result)\ + __asm__ __volatile__\ + (\ + ".align 16\n\t"\ + "1: mov %[arg], %[res]\n\t"\ + op " %%rax, %[res]\n\t"\ + "lock; cmpxchgq %[res], %[storage]\n\t"\ + "jne 1b"\ + : [orig] "+a" (original), [storage] "+m" (storage), [res] "=&r" (result)\ + : [arg] "r" (argument)\ + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory"\ + ) + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("andq", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("orq", v, original, result); + return static_cast< storage_type >(result); + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + storage_type original = storage; + storage_type result; + BOOST_ATOMIC_DETAIL_CAS_LOOP("xorq", v, original, result); + return static_cast< storage_type >(result); + } + +#undef BOOST_ATOMIC_DETAIL_CAS_LOOP + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_complement(storage, order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incq %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addq %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decq %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subq %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; negq %[storage]\n\t" + : [storage] "+m" (storage) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; andq %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; orq %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; xorq %[argument], %[storage]\n\t" + : [storage] "+m" (storage) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT + { + __asm__ __volatile__ + ( + "lock; notq %[storage]\n\t" + : [storage] "+m" (storage) + : + : "memory" + ); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incq %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addq %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "er" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; incq %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; addq %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decq %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : + : "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subq %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "er" (v) + : "memory" + ); + } +#else + if (BOOST_ATOMIC_DETAIL_IS_CONSTANT(v) && v == 1) + { + __asm__ __volatile__ + ( + "lock; decq %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } + else + { + __asm__ __volatile__ + ( + "lock; subq %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); + } +#endif + return res; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; andq %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "er" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; andq %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; orq %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "er" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; orq %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; xorq %[argument], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccnz" (res) + : [argument] "er" (v) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; xorq %[argument], %[storage]\n\t" + "setnz %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [argument] "er" (v) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btsq %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btsq %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btrq %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btrq %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + bool res; +#if defined(BOOST_ATOMIC_DETAIL_ASM_HAS_FLAG_OUTPUTS) + __asm__ __volatile__ + ( + "lock; btcq %[bit_number], %[storage]\n\t" + : [storage] "+m" (storage), [result] "=@ccc" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : "memory" + ); +#else + __asm__ __volatile__ + ( + "lock; btcq %[bit_number], %[storage]\n\t" + "setc %[result]\n\t" + : [storage] "+m" (storage), [result] "=q" (res) + : [bit_number] "Kr" ((uint64_t)bit_number) + : BOOST_ATOMIC_DETAIL_ASM_CLOBBER_CC_COMMA "memory" + ); +#endif + return res; + } +}; + +#endif // defined(__x86_64__) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GCC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_generic.hpp b/boost/atomic/detail/extra_ops_generic.hpp new file mode 100644 index 0000000..815b04c --- /dev/null +++ b/boost/atomic/detail/extra_ops_generic.hpp @@ -0,0 +1,394 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2015 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_generic.hpp + * + * This header contains generic implementation of the extra atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Generic implementation of extra operations +template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based > +struct extra_operations_generic : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< Size >::type emulated_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_add(storage, v, order) + v; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_sub(storage, v, order) - v; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_and(storage, v, order) & v; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_or(storage, v, order) | v; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_xor(storage, v, order) ^ v; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))); + return base_type::fetch_xor(storage, mask, order) ^ mask; + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_sub(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_and(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_or(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_xor(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + fetch_complement(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(add(storage, v, order)); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(sub(storage, v, order)); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order)); + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_or(storage, mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_and(storage, ~mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_xor(storage, mask, order); + return !!(old_val & mask); + } +}; + +//! Specialization for cases when the platform only natively supports CAS +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations_generic< Base, Size, Signed, true > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef typename storage_traits< Size >::type emulated_storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val; + atomics::detail::non_atomic_load(storage, old_val); + while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {} + return old_val; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val & v)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val | v)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_val); + do + { + new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val ^ v)); + } + while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed)); + return new_val; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return bitwise_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_add(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_sub(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + fetch_negate(storage, order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_and(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_or(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fetch_xor(storage, v, order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + fetch_complement(storage, order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(add(storage, v, order)); + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(sub(storage, v, order)); + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!negate(storage, order); + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_and(storage, v, order); + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_or(storage, v, order); + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + return !!bitwise_xor(storage, v, order); + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order)); + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_or(storage, mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_and(storage, ~mask, order); + return !!(old_val & mask); + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number)); + storage_type old_val = base_type::fetch_xor(storage, mask, order); + return !!(old_val & mask); + } +}; + +// Default extra_operations template definition will be used unless specialized for a specific platform +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations< Base, Size, Signed, true > : + public extra_operations_generic< Base, Size, Signed > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_msvc_arm.hpp b/boost/atomic/detail/extra_ops_msvc_arm.hpp new file mode 100644 index 0000000..bc1f4dd --- /dev/null +++ b/boost/atomic/detail/extra_ops_msvc_arm.hpp @@ -0,0 +1,108 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_msvc_arm.hpp + * + * This header contains implementation of the extra atomic operations for ARM. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR) + +template< typename Base, std::size_t Size, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED) && defined(BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE) && defined(BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE) + bool result; + switch (order) + { + case memory_order_relaxed: + result = !!BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED(&storage, bit_number); + break; + case memory_order_consume: + case memory_order_acquire: + result = !!BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE(&storage, bit_number); + break; + case memory_order_release: + result = !!BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE(&storage, bit_number); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + result = !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number); + break; + } + return result; +#else + return !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number); +#endif + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { +#if defined(BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED) && defined(BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE) && defined(BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE) + bool result; + switch (order) + { + case memory_order_relaxed: + result = !!BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED(&storage, bit_number); + break; + case memory_order_consume: + case memory_order_acquire: + result = !!BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE(&storage, bit_number); + break; + case memory_order_release: + result = !!BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE(&storage, bit_number); + break; + case memory_order_acq_rel: + case memory_order_seq_cst: + default: + result = !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number); + break; + } + return result; +#else + return !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number); +#endif + } +}; + +#endif // defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/extra_ops_msvc_x86.hpp b/boost/atomic/detail/extra_ops_msvc_x86.hpp new file mode 100644 index 0000000..78c29e1 --- /dev/null +++ b/boost/atomic/detail/extra_ops_msvc_x86.hpp @@ -0,0 +1,1328 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/extra_ops_msvc_x86.hpp + * + * This header contains implementation of the extra atomic operations for x86. + */ + +#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_X86_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(_M_IX86) + +template< typename Base, bool Signed > +struct extra_operations< Base, 1u, Signed, true > : + public extra_operations_generic< Base, 1u, Signed > +{ + typedef extra_operations_generic< Base, 1u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + neg dl + lock cmpxchg byte ptr [ecx], dl + jne again + mov old_val, al + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + neg dl + lock cmpxchg byte ptr [ecx], dl + jne again + mov new_val, dl + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + neg dl + lock cmpxchg byte ptr [ecx], dl + jne again + test dl, dl + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + neg dl + lock cmpxchg byte ptr [ecx], dl + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + and dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, dl + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + or dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, dl + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, byte ptr [edi] + align 16 + again: + mov dl, al + xor dl, cl + lock cmpxchg byte ptr [edi], dl + jne again + mov v, dl + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + not dl + lock cmpxchg byte ptr [ecx], dl + jne again + mov old_val, al + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + not dl + lock cmpxchg byte ptr [ecx], dl + jne again + mov new_val, dl + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + not dl + lock cmpxchg byte ptr [ecx], dl + jne again + test dl, dl + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + movzx eax, byte ptr [ecx] + align 16 + again: + mov edx, eax + not dl + lock cmpxchg byte ptr [ecx], dl + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock add byte ptr [edx], al + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock sub byte ptr [edx], al + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock neg byte ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock and byte ptr [edx], al + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock or byte ptr [edx], al + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock xor byte ptr [edx], al + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock not byte ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock add byte ptr [edx], al + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock sub byte ptr [edx], al + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock and byte ptr [edx], al + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock or byte ptr [edx], al + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock xor byte ptr [edx], al + setnz result + }; + base_type::fence_after(order); + return result; + } +}; + +template< typename Base, bool Signed > +struct extra_operations< Base, 2u, Signed, true > : + public extra_operations_generic< Base, 2u, Signed > +{ + typedef extra_operations_generic< Base, 2u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + neg dx + lock cmpxchg word ptr [ecx], dx + jne again + mov old_val, ax + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + neg dx + lock cmpxchg word ptr [ecx], dx + jne again + mov new_val, dx + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + neg dx + lock cmpxchg word ptr [ecx], dx + jne again + test dx, dx + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + neg dx + lock cmpxchg word ptr [ecx], dx + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + and dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, dx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + or dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, dx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + movzx ecx, v + xor edx, edx + movzx eax, word ptr [edi] + align 16 + again: + mov dx, ax + xor dx, cx + lock cmpxchg word ptr [edi], dx + jne again + mov v, dx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + not dx + lock cmpxchg word ptr [ecx], dx + jne again + mov old_val, ax + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + not dx + lock cmpxchg word ptr [ecx], dx + jne again + mov new_val, dx + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + not dx + lock cmpxchg word ptr [ecx], dx + jne again + test dx, dx + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + movzx eax, word ptr [ecx] + align 16 + again: + mov edx, eax + not dx + lock cmpxchg word ptr [ecx], dx + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock add word ptr [edx], ax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock sub word ptr [edx], ax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock neg word ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock and word ptr [edx], ax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock or word ptr [edx], ax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + movzx eax, v + lock xor word ptr [edx], ax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock not word ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock add word ptr [edx], ax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock sub word ptr [edx], ax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock and word ptr [edx], ax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock or word ptr [edx], ax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + movzx eax, v + lock xor word ptr [edx], ax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock bts word ptr [edx], ax + setc result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock btr word ptr [edx], ax + setc result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock btc word ptr [edx], ax + setc result + }; + base_type::fence_after(order); + return result; + } +}; + +#endif // defined(_M_IX86) + +#if defined(_M_IX86) || (defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR)) + +template< typename Base, bool Signed > +struct extra_operations< Base, 4u, Signed, true > : + public extra_operations_generic< Base, 4u, Signed > +{ + typedef extra_operations_generic< Base, 4u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + +#if defined(_M_IX86) + static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + neg edx + lock cmpxchg dword ptr [ecx], edx + jne again + mov old_val, eax + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + neg edx + lock cmpxchg dword ptr [ecx], edx + jne again + mov new_val, edx + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + neg edx + lock cmpxchg dword ptr [ecx], edx + jne again + test edx, edx + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + neg edx + lock cmpxchg dword ptr [ecx], edx + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + mov ecx, v + xor edx, edx + mov eax, dword ptr [edi] + align 16 + again: + mov edx, eax + and edx, ecx + lock cmpxchg dword ptr [edi], edx + jne again + mov v, edx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + mov ecx, v + xor edx, edx + mov eax, dword ptr [edi] + align 16 + again: + mov edx, eax + or edx, ecx + lock cmpxchg dword ptr [edi], edx + jne again + mov v, edx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edi, storage + mov ecx, v + xor edx, edx + mov eax, dword ptr [edi] + align 16 + again: + mov edx, eax + xor edx, ecx + lock cmpxchg dword ptr [edi], edx + jne again + mov v, edx + }; + base_type::fence_after(order); + return v; + } + + static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type old_val; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + not edx + lock cmpxchg dword ptr [ecx], edx + jne again + mov old_val, eax + }; + base_type::fence_after(order); + return old_val; + } + + static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + storage_type new_val; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + not edx + lock cmpxchg dword ptr [ecx], edx + jne again + mov new_val, edx + }; + base_type::fence_after(order); + return new_val; + } + + static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + not edx + lock cmpxchg dword ptr [ecx], edx + jne again + test edx, edx + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov ecx, storage + mov eax, dword ptr [ecx] + align 16 + again: + mov edx, eax + not edx + lock cmpxchg dword ptr [ecx], edx + jne again + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + mov eax, v + lock add dword ptr [edx], eax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + mov eax, v + lock sub dword ptr [edx], eax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock neg dword ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + mov eax, v + lock and dword ptr [edx], eax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + mov eax, v + lock or dword ptr [edx], eax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + mov eax, v + lock xor dword ptr [edx], eax + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + __asm + { + mov edx, storage + lock not dword ptr [edx] + }; + base_type::fence_after(order); + } + + static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, v + lock add dword ptr [edx], eax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, v + lock sub dword ptr [edx], eax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, v + lock and dword ptr [edx], eax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, v + lock or dword ptr [edx], eax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, v + lock xor dword ptr [edx], eax + setnz result + }; + base_type::fence_after(order); + return result; + } + + static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock btc dword ptr [edx], eax + setc result + }; + base_type::fence_after(order); + return result; + } +#endif // defined(_M_IX86) + +#if defined(BOOST_ATOMIC_INTERLOCKED_BTS) + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + return !!BOOST_ATOMIC_INTERLOCKED_BTS(&storage, bit_number); + } +#elif defined(_M_IX86) + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock bts dword ptr [edx], eax + setc result + }; + base_type::fence_after(order); + return result; + } +#endif + +#if defined(BOOST_ATOMIC_INTERLOCKED_BTR) + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order) BOOST_NOEXCEPT + { + return !!BOOST_ATOMIC_INTERLOCKED_BTR(&storage, bit_number); + } +#elif defined(_M_IX86) + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + base_type::fence_before(order); + bool result; + __asm + { + mov edx, storage + mov eax, bit_number + lock btr dword ptr [edx], eax + setc result + }; + base_type::fence_after(order); + return result; + } +#endif +}; + +#endif // defined(_M_IX86) || (defined(BOOST_ATOMIC_INTERLOCKED_BTS) && defined(BOOST_ATOMIC_INTERLOCKED_BTR)) + +#if defined(BOOST_ATOMIC_INTERLOCKED_BTS64) && defined(BOOST_ATOMIC_INTERLOCKED_BTR64) + +template< typename Base, bool Signed > +struct extra_operations< Base, 8u, Signed, true > : + public extra_operations_generic< Base, 8u, Signed > +{ + typedef extra_operations_generic< Base, 8u, Signed > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + return !!BOOST_ATOMIC_INTERLOCKED_BTS64(&storage, bit_number); + } + + static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT + { + return !!BOOST_ATOMIC_INTERLOCKED_BTR64(&storage, bit_number); + } +}; + +#endif // defined(BOOST_ATOMIC_INTERLOCKED_BTS64) && defined(BOOST_ATOMIC_INTERLOCKED_BTR64) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_MSVC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_operations.hpp b/boost/atomic/detail/fence_arch_operations.hpp new file mode 100644 index 0000000..912b5db --- /dev/null +++ b/boost/atomic/detail/fence_arch_operations.hpp @@ -0,0 +1,41 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_operations.hpp + * + * This header defines architecture-specific fence atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(boost/atomic/detail/fence_arch_ops_) +#else +#include + +namespace boost { +namespace atomics { +namespace detail { + +typedef fence_operations_emulated fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_aarch32.hpp b/boost/atomic/detail/fence_arch_ops_gcc_aarch32.hpp new file mode 100644 index 0000000..6a8ce4a --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_aarch32.hpp @@ -0,0 +1,60 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_aarch32.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for AArch32 +struct fence_arch_operations_gcc_aarch32 +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + { + if (order == memory_order_consume || order == memory_order_acquire) + __asm__ __volatile__ ("dmb ishld\n\t" ::: "memory"); + else + __asm__ __volatile__ ("dmb ish\n\t" ::: "memory"); + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_arch_operations_gcc_aarch32 fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH32_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_aarch64.hpp b/boost/atomic/detail/fence_arch_ops_gcc_aarch64.hpp new file mode 100644 index 0000000..66f374a --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_aarch64.hpp @@ -0,0 +1,58 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_aarch64.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for AArch64 +struct fence_arch_operations_gcc_aarch64 +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + { + if (order == memory_order_consume || order == memory_order_acquire) + __asm__ __volatile__ ("dmb ishld\n\t" ::: "memory"); + else + __asm__ __volatile__ ("dmb ish\n\t" ::: "memory"); + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_arch_operations_gcc_aarch64 fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_AARCH64_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_alpha.hpp b/boost/atomic/detail/fence_arch_ops_gcc_alpha.hpp new file mode 100644 index 0000000..0c81ed2 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_alpha.hpp @@ -0,0 +1,53 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_alpha.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for Alpha +struct fence_arch_operations_gcc_alpha +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("mb" ::: "memory"); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_arch_operations_gcc_alpha fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ALPHA_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_arm.hpp b/boost/atomic/detail/fence_arch_ops_gcc_arm.hpp new file mode 100644 index 0000000..537a5c7 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_arm.hpp @@ -0,0 +1,90 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_arm.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for legacy ARM +struct fence_arch_operations_gcc_arm +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + hardware_full_fence(); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } + + static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT + { + // A memory barrier is effected using a "co-processor 15" instruction, + // though a separate assembler mnemonic is available for it in v7. + +#if defined(BOOST_ATOMIC_DETAIL_ARM_HAS_DMB) + // Older binutils (supposedly, older than 2.21.1) didn't support symbolic or numeric arguments of the "dmb" instruction such as "ish" or "#11". + // As a workaround we have to inject encoded bytes of the instruction. There are two encodings for the instruction: ARM and Thumb. See ARM Architecture Reference Manual, A8.8.43. + // Since we cannot detect binutils version at compile time, we'll have to always use this hack. + __asm__ __volatile__ + ( +#if defined(__thumb2__) + ".short 0xF3BF, 0x8F5B\n\t" // dmb ish +#else + ".word 0xF57FF05B\n\t" // dmb ish +#endif + : + : + : "memory" + ); +#else + uint32_t tmp; + __asm__ __volatile__ + ( + BOOST_ATOMIC_DETAIL_ARM_ASM_START(%0) + "mcr p15, 0, r0, c7, c10, 5\n\t" + BOOST_ATOMIC_DETAIL_ARM_ASM_END(%0) + : "=&l" (tmp) + : + : "memory" + ); +#endif + } +}; + +typedef fence_arch_operations_gcc_arm fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_ppc.hpp b/boost/atomic/detail/fence_arch_ops_gcc_ppc.hpp new file mode 100644 index 0000000..e161ae4 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_ppc.hpp @@ -0,0 +1,68 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_ppc.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for PowerPC +struct fence_arch_operations_gcc_ppc +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + { +#if defined(__powerpc64__) || defined(__PPC64__) + if (order != memory_order_seq_cst) + __asm__ __volatile__ ("lwsync" ::: "memory"); + else + __asm__ __volatile__ ("sync" ::: "memory"); +#else + __asm__ __volatile__ ("sync" ::: "memory"); +#endif + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + { +#if defined(__ibmxl__) || defined(__IBMCPP__) + __fence(); +#else + __asm__ __volatile__ ("" ::: "memory"); +#endif + } + } +}; + +typedef fence_arch_operations_gcc_ppc fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_PPC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_sparc.hpp b/boost/atomic/detail/fence_arch_ops_gcc_sparc.hpp new file mode 100644 index 0000000..5c18111 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_sparc.hpp @@ -0,0 +1,70 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_sparc.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for SPARC +struct fence_arch_operations_gcc_sparc +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + switch (order) + { + case memory_order_release: + __asm__ __volatile__ ("membar #StoreStore | #LoadStore" ::: "memory"); + break; + case memory_order_consume: + case memory_order_acquire: + __asm__ __volatile__ ("membar #LoadLoad | #LoadStore" ::: "memory"); + break; + case memory_order_acq_rel: + __asm__ __volatile__ ("membar #LoadLoad | #LoadStore | #StoreStore" ::: "memory"); + break; + case memory_order_seq_cst: + __asm__ __volatile__ ("membar #Sync" ::: "memory"); + break; + case memory_order_relaxed: + default: + break; + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_arch_operations_gcc_sparc fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_SPARC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_gcc_x86.hpp b/boost/atomic/detail/fence_arch_ops_gcc_x86.hpp new file mode 100644 index 0000000..0cb61f6 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_gcc_x86.hpp @@ -0,0 +1,69 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_gcc_x86.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for x86 +struct fence_arch_operations_gcc_x86 +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + { + // We could generate mfence for a seq_cst fence here, but a dummy lock-prefixed instruction is enough + // and is faster than mfence on most modern x86 CPUs (as of 2020). + // Note that we want to apply the atomic operation on any location so that: + // - It is not shared with other threads. A variable on the stack suits this well. + // - It is likely in cache. Being close to the top of the stack fits this well. + // - It does not alias existing data on the stack, so that we don't introduce a false data dependency. + // See some performance data here: https://shipilev.net/blog/2014/on-the-fence-with-dependencies/ + // Unfortunately, to make tools like valgrind happy, we have to initialize the dummy, which is + // otherwise not needed. + unsigned char dummy = 0u; + __asm__ __volatile__ ("lock; notb %0" : "+m" (dummy) : : "memory"); + } + else if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_acquire) | static_cast< unsigned int >(memory_order_release))) != 0u) + { + __asm__ __volatile__ ("" ::: "memory"); + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_arch_operations_gcc_x86 fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_GCC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_msvc_arm.hpp b/boost/atomic/detail/fence_arch_ops_msvc_arm.hpp new file mode 100644 index 0000000..6647d00 --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_msvc_arm.hpp @@ -0,0 +1,66 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_msvc_arm.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ + +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +extern "C" void __dmb(unsigned int); +#if defined(BOOST_MSVC) +#pragma intrinsic(__dmb) +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for ARM +struct fence_arch_operations_msvc_arm +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + if (order != memory_order_relaxed) + hardware_full_fence(); + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT + { + __dmb(0xB); // _ARM_BARRIER_ISH, see armintr.h from MSVC 11 and later + } +}; + +typedef fence_arch_operations_msvc_arm fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_arch_ops_msvc_x86.hpp b/boost/atomic/detail/fence_arch_ops_msvc_x86.hpp new file mode 100644 index 0000000..8ead6df --- /dev/null +++ b/boost/atomic/detail/fence_arch_ops_msvc_x86.hpp @@ -0,0 +1,66 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_arch_ops_msvc_x86.hpp + * + * This header contains implementation of the \c fence_arch_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations for x86 +struct fence_arch_operations_msvc_x86 +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + { + // See the comment in fence_ops_gcc_x86.hpp as to why we're not using mfence here. + // We're not using __faststorefence() here because it generates an atomic operation + // on [rsp]/[esp] location, which may alias valid data and cause false data dependency. + boost::uint32_t dummy; + BOOST_ATOMIC_INTERLOCKED_INCREMENT(&dummy); + } + else if (order != memory_order_relaxed) + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } +}; + +typedef fence_arch_operations_msvc_x86 fence_arch_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_ARCH_OPS_MSVC_X86_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_operations.hpp b/boost/atomic/detail/fence_operations.hpp new file mode 100644 index 0000000..ec87126 --- /dev/null +++ b/boost/atomic/detail/fence_operations.hpp @@ -0,0 +1,41 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_operations.hpp + * + * This header defines fence atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER) +#include BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(boost/atomic/detail/fence_ops_) +#else +#include + +namespace boost { +namespace atomics { +namespace detail { + +typedef fence_arch_operations fence_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_operations_emulated.hpp b/boost/atomic/detail/fence_operations_emulated.hpp new file mode 100644 index 0000000..adcb2ee --- /dev/null +++ b/boost/atomic/detail/fence_operations_emulated.hpp @@ -0,0 +1,50 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_operations_emulated.hpp + * + * This header contains implementation of the \c fence_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations based on lock pool +struct fence_operations_emulated +{ + static BOOST_FORCEINLINE void thread_fence(memory_order) BOOST_NOEXCEPT + { + atomics::detail::lock_pool::thread_fence(); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order) BOOST_NOEXCEPT + { + atomics::detail::lock_pool::signal_fence(); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPERATIONS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_ops_gcc_atomic.hpp b/boost/atomic/detail/fence_ops_gcc_atomic.hpp new file mode 100644 index 0000000..5fa2277 --- /dev/null +++ b/boost/atomic/detail/fence_ops_gcc_atomic.hpp @@ -0,0 +1,75 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_ops_gcc_atomic.hpp + * + * This header contains implementation of the \c fence_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__INTEL_COMPILER) +// This is used to suppress warning #32013 described in gcc_atomic_memory_order_utils.hpp +// for Intel Compiler. +// In debug builds the compiler does not inline any functions, so basically +// every atomic function call results in this warning. I don't know any other +// way to selectively disable just this one warning. +#pragma system_header +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations based on gcc __atomic* intrinsics +struct fence_operations_gcc_atomic +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { +#if defined(__x86_64__) || defined(__i386__) + if (order != memory_order_seq_cst) + { + __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order)); + } + else + { + // gcc, clang, icc and probably other compilers generate mfence for a seq_cst fence, + // while a dummy lock-prefixed instruction would be enough and faster. See the comment in fence_ops_gcc_x86.hpp. + fence_arch_operations::thread_fence(order); + } +#else + __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order)); +#endif + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + __atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order)); + } +}; + +typedef fence_operations_gcc_atomic fence_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_ATOMIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_ops_gcc_sync.hpp b/boost/atomic/detail/fence_ops_gcc_sync.hpp new file mode 100644 index 0000000..8fa03ac --- /dev/null +++ b/boost/atomic/detail/fence_ops_gcc_sync.hpp @@ -0,0 +1,53 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_ops_gcc_sync.hpp + * + * This header contains implementation of the \c fence_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations based on gcc __sync* intrinsics +struct fence_operations_gcc_sync +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __sync_synchronize(); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } +}; + +typedef fence_operations_gcc_sync fence_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_GCC_SYNC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_ops_linux_arm.hpp b/boost/atomic/detail/fence_ops_linux_arm.hpp new file mode 100644 index 0000000..218ee30 --- /dev/null +++ b/boost/atomic/detail/fence_ops_linux_arm.hpp @@ -0,0 +1,64 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009, 2011 Helge Bahmann + * Copyright (c) 2009 Phil Endecott + * Copyright (c) 2013 Tim Blechmann + * Linux-specific code by Phil Endecott + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_ops_linux_arm.hpp + * + * This header contains implementation of the \c fence_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations based on Linux-specific system routines +struct fence_operations_linux_arm +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + hardware_full_fence(); + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + __asm__ __volatile__ ("" ::: "memory"); + } + + static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT + { + // See the comment in core_ops_linux_arm.hpp regarding the function pointer below + typedef void (*kernel_dmb_t)(void); + ((kernel_dmb_t)0xffff0fa0)(); + } +}; + +typedef fence_operations_linux_arm fence_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_LINUX_ARM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fence_ops_windows.hpp b/boost/atomic/detail/fence_ops_windows.hpp new file mode 100644 index 0000000..68f02bd --- /dev/null +++ b/boost/atomic/detail/fence_ops_windows.hpp @@ -0,0 +1,67 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/fence_ops_windows.hpp + * + * This header contains implementation of the \c fence_operations struct. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Fence operations based on Windows-specific system calls or intrinsics +struct fence_operations_windows +{ + static BOOST_FORCEINLINE void thread_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + { + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + if (order == memory_order_seq_cst) + hardware_full_fence(); + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + } + + static BOOST_FORCEINLINE void signal_fence(memory_order order) BOOST_NOEXCEPT + { + if (order != memory_order_relaxed) + BOOST_ATOMIC_DETAIL_COMPILER_BARRIER(); + } + + static BOOST_FORCEINLINE void hardware_full_fence() BOOST_NOEXCEPT + { + boost::uint32_t tmp; + BOOST_ATOMIC_INTERLOCKED_INCREMENT(&tmp); + } +}; + +typedef fence_operations_windows fence_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FENCE_OPS_WINDOWS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/float_sizes.hpp b/boost/atomic/detail/float_sizes.hpp new file mode 100644 index 0000000..4c3a346 --- /dev/null +++ b/boost/atomic/detail/float_sizes.hpp @@ -0,0 +1,142 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/float_sizes.hpp + * + * This header defines macros for testing buitin floating point type sizes + */ + +#ifndef BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Detect value sizes of the different floating point types. The value sizes may be less than the corresponding type sizes +// if the type contains padding bits. This is typical e.g. with 80-bit extended float types, which are often represented as 128-bit types. +// See: https://en.wikipedia.org/wiki/IEEE_754 +// For Intel x87 extended double see: https://en.wikipedia.org/wiki/Extended_precision#x86_Architecture_Extended_Precision_Format +// For IBM extended double (a.k.a. double-double) see: https://en.wikipedia.org/wiki/Long_double#Implementations, https://gcc.gnu.org/wiki/Ieee128PowerPC +#if (FLT_RADIX+0) == 2 + +#if ((FLT_MANT_DIG+0) == 11) && ((FLT_MAX_EXP+0) == 16) // IEEE 754 binary16 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 2 +#elif ((FLT_MANT_DIG+0) == 24) && ((FLT_MAX_EXP+0) == 128) // IEEE 754 binary32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 4 +#elif ((FLT_MANT_DIG+0) == 53) && ((FLT_MAX_EXP+0) == 1024) // IEEE 754 binary64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 8 +#elif ((FLT_MANT_DIG+0) == 64) && ((FLT_MAX_EXP+0) == 16384) // x87 extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 10 +#elif ((FLT_MANT_DIG+0) == 106) && ((FLT_MAX_EXP+0) == 1024) // IBM extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16 +#elif ((FLT_MANT_DIG+0) == 113) && ((FLT_MAX_EXP+0) == 16384) // IEEE 754 binary128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16 +#elif ((FLT_MANT_DIG+0) == 237) && ((FLT_MAX_EXP+0) == 262144) // IEEE 754 binary256 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 32 +#endif + +#if ((DBL_MANT_DIG+0) == 11) && ((DBL_MAX_EXP+0) == 16) // IEEE 754 binary16 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 2 +#elif ((DBL_MANT_DIG+0) == 24) && ((DBL_MAX_EXP+0) == 128) // IEEE 754 binary32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 4 +#elif ((DBL_MANT_DIG+0) == 53) && ((DBL_MAX_EXP+0) == 1024) // IEEE 754 binary64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 8 +#elif ((DBL_MANT_DIG+0) == 64) && ((DBL_MAX_EXP+0) == 16384) // x87 extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 10 +#elif ((DBL_MANT_DIG+0) == 106) && ((DBL_MAX_EXP+0) == 1024) // IBM extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16 +#elif ((DBL_MANT_DIG+0) == 113) && ((DBL_MAX_EXP+0) == 16384) // IEEE 754 binary128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16 +#elif ((DBL_MANT_DIG+0) == 237) && ((DBL_MAX_EXP+0) == 262144) // IEEE 754 binary256 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 32 +#endif + +#if ((LDBL_MANT_DIG+0) == 11) && ((LDBL_MAX_EXP+0) == 16) // IEEE 754 binary16 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 2 +#elif ((LDBL_MANT_DIG+0) == 24) && ((LDBL_MAX_EXP+0) == 128) // IEEE 754 binary32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 4 +#elif ((LDBL_MANT_DIG+0) == 53) && ((LDBL_MAX_EXP+0) == 1024) // IEEE 754 binary64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 8 +#elif ((LDBL_MANT_DIG+0) == 64) && ((LDBL_MAX_EXP+0) == 16384) // x87 extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 10 +#elif ((LDBL_MANT_DIG+0) == 106) && ((LDBL_MAX_EXP+0) == 1024) // IBM extended double +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16 +#elif ((LDBL_MANT_DIG+0) == 113) && ((LDBL_MAX_EXP+0) == 16384) // IEEE 754 binary128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16 +#elif ((LDBL_MANT_DIG+0) == 237) && ((LDBL_MAX_EXP+0) == 262144) // IEEE 754 binary256 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 32 +#endif + +#elif (FLT_RADIX+0) == 10 + +#if ((FLT_MANT_DIG+0) == 7) && ((FLT_MAX_EXP+0) == 97) // IEEE 754 decimal32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 4 +#elif ((FLT_MANT_DIG+0) == 16) && ((FLT_MAX_EXP+0) == 385) // IEEE 754 decimal64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 8 +#elif ((FLT_MANT_DIG+0) == 34) && ((FLT_MAX_EXP+0) == 6145) // IEEE 754 decimal128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE 16 +#endif + +#if ((DBL_MANT_DIG+0) == 7) && ((DBL_MAX_EXP+0) == 97) // IEEE 754 decimal32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 4 +#elif ((DBL_MANT_DIG+0) == 16) && ((DBL_MAX_EXP+0) == 385) // IEEE 754 decimal64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 8 +#elif ((DBL_MANT_DIG+0) == 34) && ((DBL_MAX_EXP+0) == 6145) // IEEE 754 decimal128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE 16 +#endif + +#if ((LDBL_MANT_DIG+0) == 7) && ((LDBL_MAX_EXP+0) == 97) // IEEE 754 decimal32 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 4 +#elif ((LDBL_MANT_DIG+0) == 16) && ((LDBL_MAX_EXP+0) == 385) // IEEE 754 decimal64 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 8 +#elif ((LDBL_MANT_DIG+0) == 34) && ((LDBL_MAX_EXP+0) == 6145) // IEEE 754 decimal128 +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE 16 +#endif + +#endif + +// GCC and compatible compilers define internal macros with builtin type traits +#if defined(__SIZEOF_FLOAT__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT __SIZEOF_FLOAT__ +#endif +#if defined(__SIZEOF_DOUBLE__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE __SIZEOF_DOUBLE__ +#endif +#if defined(__SIZEOF_LONG_DOUBLE__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE __SIZEOF_LONG_DOUBLE__ +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) + +#define BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(x)\ + ((x) == 1u ? 1u : ((x) == 2u ? 2u : ((x) <= 4u ? 4u : ((x) <= 8u ? 8u : ((x) <= 16u ? 16u : ((x) <= 32u ? 32u : (x))))))) + +// Make our best guess. These sizes may not be accurate, but they are good enough to estimate the size of the storage required to hold these types. +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE) +#define BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE) +#endif +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE) +#define BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE) +#endif +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE BOOST_ATOMIC_DETAIL_ALIGN_SIZE_TO_POWER_OF_2(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE) +#endif + +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE_VALUE) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) +#error Boost.Atomic: Failed to determine builtin floating point type sizes, the target platform is not supported. Please, report to the developers (patches are welcome). +#endif + +#endif // BOOST_ATOMIC_DETAIL_FLOAT_SIZES_HPP_INCLUDED_ diff --git a/boost/atomic/detail/footer.hpp b/boost/atomic/detail/footer.hpp new file mode 100644 index 0000000..5134719 --- /dev/null +++ b/boost/atomic/detail/footer.hpp @@ -0,0 +1,24 @@ +/* + * Copyright Andrey Semashev 2020. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#if !defined(BOOST_ATOMIC_ENABLE_WARNINGS) + +#if defined(BOOST_MSVC) + +#pragma warning(pop) + +#elif defined(BOOST_GCC) && BOOST_GCC >= 40600 + +#pragma GCC diagnostic pop + +#elif defined(BOOST_CLANG) + +#pragma clang diagnostic pop + +#endif + +#endif // !defined(BOOST_ATOMIC_ENABLE_WARNINGS) diff --git a/boost/atomic/detail/fp_operations.hpp b/boost/atomic/detail/fp_operations.hpp new file mode 100644 index 0000000..69cb0d1 --- /dev/null +++ b/boost/atomic/detail/fp_operations.hpp @@ -0,0 +1,28 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/fp_operations.hpp + * + * This header defines floating point atomic operations, including the generic version. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if !defined(BOOST_ATOMIC_DETAIL_FP_BACKEND_GENERIC) +#include BOOST_ATOMIC_DETAIL_FP_BACKEND_HEADER(boost/atomic/detail/fp_ops_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_FP_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fp_operations_fwd.hpp b/boost/atomic/detail/fp_operations_fwd.hpp new file mode 100644 index 0000000..c83a307 --- /dev/null +++ b/boost/atomic/detail/fp_operations_fwd.hpp @@ -0,0 +1,38 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/fp_operations_fwd.hpp + * + * This header contains forward declaration of the \c fp_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, typename Value, std::size_t Size = sizeof(typename Base::storage_type), bool = Base::is_always_lock_free > +struct fp_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FP_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fp_ops_emulated.hpp b/boost/atomic/detail/fp_ops_emulated.hpp new file mode 100644 index 0000000..d9d77e3 --- /dev/null +++ b/boost/atomic/detail/fp_ops_emulated.hpp @@ -0,0 +1,78 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/fp_ops_emulated.hpp + * + * This header contains emulated (lock-based) implementation of the floating point atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Emulated implementation of floating point operations +template< typename Base, typename Value, std::size_t Size > +struct fp_operations_emulated : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + typedef typename base_type::scoped_lock scoped_lock; + + static value_type fetch_add(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = old_val + v; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return old_val; + } + + static value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type& s = const_cast< storage_type& >(storage); + scoped_lock lock(&storage); + value_type old_val = atomics::detail::bitwise_fp_cast< value_type >(s); + value_type new_val = old_val - v; + s = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + return old_val; + } +}; + +template< typename Base, typename Value, std::size_t Size > +struct fp_operations< Base, Value, Size, false > : + public fp_operations_emulated< Base, Value, Size > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FP_OPS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/fp_ops_generic.hpp b/boost/atomic/detail/fp_ops_generic.hpp new file mode 100644 index 0000000..05979f2 --- /dev/null +++ b/boost/atomic/detail/fp_ops_generic.hpp @@ -0,0 +1,86 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/fp_ops_generic.hpp + * + * This header contains generic implementation of the floating point atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Generic implementation of floating point operations +template< typename Base, typename Value, std::size_t Size > +struct fp_operations_generic : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef Value value_type; + + static BOOST_FORCEINLINE value_type fetch_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = old_val + v; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return old_val; + } + + static BOOST_FORCEINLINE value_type fetch_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT + { + storage_type old_storage, new_storage; + value_type old_val, new_val; + atomics::detail::non_atomic_load(storage, old_storage); + do + { + old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage); + new_val = old_val - v; + new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val); + } + while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed)); + return old_val; + } +}; + +// Default fp_operations template definition will be used unless specialized for a specific platform +template< typename Base, typename Value, std::size_t Size > +struct fp_operations< Base, Value, Size, true > : + public fp_operations_generic< Base, Value, Size > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/futex.hpp b/boost/atomic/detail/futex.hpp new file mode 100644 index 0000000..f5cb989 --- /dev/null +++ b/boost/atomic/detail/futex.hpp @@ -0,0 +1,154 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/futex.hpp + * + * This header defines wrappers around futex syscall. + * + * http://man7.org/linux/man-pages/man2/futex.2.html + * https://man.openbsd.org/futex + */ + +#ifndef BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__linux__) || defined(__OpenBSD__) || defined(__NETBSD__) || defined(__NetBSD__) + +#include + +#if defined(SYS_futex) +#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS_futex +#elif defined(SYS_futex_time64) +// On some 32-bit targets (e.g. riscv32) SYS_futex is not defined and instead SYS_futex_time64 is implemented, +// which is equivalent to SYS_futex but uses 64-bit time_t. +#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS_futex_time64 +#elif defined(__NR_futex) +// Some Android NDKs (Google NDK and older Crystax.NET NDK versions) don't define SYS_futex. +#define BOOST_ATOMIC_DETAIL_SYS_FUTEX __NR_futex +#elif defined(SYS___futex) +// NetBSD defines SYS___futex, which has slightly different parameters. Basically, it has decoupled timeout and val2 parameters: +// int __futex(int *addr1, int op, int val1, const struct timespec *timeout, int *addr2, int val2, int val3); +// https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/sys/syscall.h +// http://bxr.su/NetBSD/sys/kern/sys_futex.c +#define BOOST_ATOMIC_DETAIL_SYS_FUTEX SYS___futex +#define BOOST_ATOMIC_DETAIL_NETBSD_FUTEX +#endif + +#if defined(BOOST_ATOMIC_DETAIL_SYS_FUTEX) + +#include +#if defined(__linux__) +#include +#else +#include +#endif +#include +#include + +#define BOOST_ATOMIC_DETAIL_HAS_FUTEX + +#if defined(FUTEX_PRIVATE_FLAG) +#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG FUTEX_PRIVATE_FLAG +#elif defined(__ANDROID__) +// On Android, futex.h is lacking many definitions, but the actual Linux kernel supports the API in full. +#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG 128 +#else +#define BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG 0 +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Invokes an operation on the futex +BOOST_FORCEINLINE int futex_invoke(void* addr1, int op, unsigned int val1, const void* timeout = NULL, void* addr2 = NULL, unsigned int val3 = 0) BOOST_NOEXCEPT +{ +#if !defined(BOOST_ATOMIC_DETAIL_NETBSD_FUTEX) + return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, timeout, addr2, val3); +#else + // Pass 0 in val2. + return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, timeout, addr2, 0u, val3); +#endif +} + +//! Invokes an operation on the futex +BOOST_FORCEINLINE int futex_invoke(void* addr1, int op, unsigned int val1, unsigned int val2, void* addr2 = NULL, unsigned int val3 = 0) BOOST_NOEXCEPT +{ +#if !defined(BOOST_ATOMIC_DETAIL_NETBSD_FUTEX) + return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, static_cast< atomics::detail::uintptr_t >(val2), addr2, val3); +#else + // Pass NULL in timeout. + return ::syscall(BOOST_ATOMIC_DETAIL_SYS_FUTEX, addr1, op, val1, static_cast< void* >(NULL), addr2, val2, val3); +#endif +} + +//! Checks that the value \c pval is \c expected and blocks +BOOST_FORCEINLINE int futex_wait(void* pval, unsigned int expected) BOOST_NOEXCEPT +{ + return futex_invoke(pval, FUTEX_WAIT, expected); +} + +//! Checks that the value \c pval is \c expected and blocks +BOOST_FORCEINLINE int futex_wait_private(void* pval, unsigned int expected) BOOST_NOEXCEPT +{ + return futex_invoke(pval, FUTEX_WAIT | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, expected); +} + +//! Wakes the specified number of threads waiting on the futex +BOOST_FORCEINLINE int futex_signal(void* pval, unsigned int count = 1u) BOOST_NOEXCEPT +{ + return futex_invoke(pval, FUTEX_WAKE, count); +} + +//! Wakes the specified number of threads waiting on the futex +BOOST_FORCEINLINE int futex_signal_private(void* pval, unsigned int count = 1u) BOOST_NOEXCEPT +{ + return futex_invoke(pval, FUTEX_WAKE | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, count); +} + +//! Wakes all threads waiting on the futex +BOOST_FORCEINLINE int futex_broadcast(void* pval) BOOST_NOEXCEPT +{ + return futex_signal(pval, (~static_cast< unsigned int >(0u)) >> 1); +} + +//! Wakes all threads waiting on the futex +BOOST_FORCEINLINE int futex_broadcast_private(void* pval) BOOST_NOEXCEPT +{ + return futex_signal_private(pval, (~static_cast< unsigned int >(0u)) >> 1); +} + +//! Wakes the wake_count threads waiting on the futex pval1 and requeues up to requeue_count of the blocked threads onto another futex pval2 +BOOST_FORCEINLINE int futex_requeue(void* pval1, void* pval2, unsigned int wake_count = 1u, unsigned int requeue_count = (~static_cast< unsigned int >(0u)) >> 1) BOOST_NOEXCEPT +{ + return futex_invoke(pval1, FUTEX_REQUEUE, wake_count, requeue_count, pval2); +} + +//! Wakes the wake_count threads waiting on the futex pval1 and requeues up to requeue_count of the blocked threads onto another futex pval2 +BOOST_FORCEINLINE int futex_requeue_private(void* pval1, void* pval2, unsigned int wake_count = 1u, unsigned int requeue_count = (~static_cast< unsigned int >(0u)) >> 1) BOOST_NOEXCEPT +{ + return futex_invoke(pval1, FUTEX_REQUEUE | BOOST_ATOMIC_DETAIL_FUTEX_PRIVATE_FLAG, wake_count, requeue_count, pval2); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // defined(BOOST_ATOMIC_DETAIL_SYS_FUTEX) + +#endif // defined(__linux__) || defined(__OpenBSD__) || defined(__NETBSD__) || defined(__NetBSD__) + +#endif // BOOST_ATOMIC_DETAIL_FUTEX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/gcc_arm_asm_common.hpp b/boost/atomic/detail/gcc_arm_asm_common.hpp new file mode 100644 index 0000000..f13d2ba --- /dev/null +++ b/boost/atomic/detail/gcc_arm_asm_common.hpp @@ -0,0 +1,79 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/gcc_arm_asm_common.hpp + * + * This header contains basic utilities for gcc asm-based ARM backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// A memory barrier is effected using a "co-processor 15" instruction, +// though a separate assembler mnemonic is available for it in v7. +// +// "Thumb 1" is a subset of the ARM instruction set that uses a 16-bit encoding. It +// doesn't include all instructions and in particular it doesn't include the co-processor +// instruction used for the memory barrier or the load-locked/store-conditional +// instructions. So, if we're compiling in "Thumb 1" mode, we need to wrap all of our +// asm blocks with code to temporarily change to ARM mode. +// +// You can only change between ARM and Thumb modes when branching using the bx instruction. +// bx takes an address specified in a register. The least significant bit of the address +// indicates the mode, so 1 is added to indicate that the destination code is Thumb. +// A temporary register is needed for the address and is passed as an argument to these +// macros. It must be one of the "low" registers accessible to Thumb code, specified +// using the "l" attribute in the asm statement. +// +// Architecture v7 introduces "Thumb 2", which does include (almost?) all of the ARM +// instruction set. (Actually, there was an extension of v6 called v6T2 which supported +// "Thumb 2" mode, but its architecture manual is no longer available, referring to v7.) +// So in v7 we don't need to change to ARM mode; we can write "universal +// assembler" which will assemble to Thumb 2 or ARM code as appropriate. The only thing +// we need to do to make this "universal" assembler mode work is to insert "IT" instructions +// to annotate the conditional instructions. These are ignored in other modes (e.g. v6), +// so they can always be present. + +// A note about memory_order_consume. Technically, this architecture allows to avoid +// unnecessary memory barrier after consume load since it supports data dependency ordering. +// However, some compiler optimizations may break a seemingly valid code relying on data +// dependency tracking by injecting bogus branches to aid out of order execution. +// This may happen not only in Boost.Atomic code but also in user's code, which we have no +// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php. +// For this reason we promote memory_order_consume to memory_order_acquire. + +#if defined(__thumb__) && !defined(__thumb2__) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG) "adr " #TMPREG ", 8f\n\t" "bx " #TMPREG "\n\t" ".arm\n\t" ".align 4\n\t" "8:\n\t" +#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG) "adr " #TMPREG ", 9f + 1\n\t" "bx " #TMPREG "\n\t" ".thumb\n\t" ".align 2\n\t" "9:\n\t" +#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&l" (var) +#else +// Indicate that start/end macros are empty and the tmpreg is not needed +#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_UNUSED +#define BOOST_ATOMIC_DETAIL_ARM_ASM_START(TMPREG) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_END(TMPREG) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_TMPREG_CONSTRAINT(var) "=&l" (var) +#endif + +#if defined(BOOST_ATOMIC_DETAIL_ARM_LITTLE_ENDIAN) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(arg) "%" BOOST_STRINGIZE(arg) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(arg) "%H" BOOST_STRINGIZE(arg) +#else +#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_LO(arg) "%H" BOOST_STRINGIZE(arg) +#define BOOST_ATOMIC_DETAIL_ARM_ASM_ARG_HI(arg) "%" BOOST_STRINGIZE(arg) +#endif + +#endif // BOOST_ATOMIC_DETAIL_GCC_ARM_ASM_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/gcc_atomic_memory_order_utils.hpp b/boost/atomic/detail/gcc_atomic_memory_order_utils.hpp new file mode 100644 index 0000000..42f5212 --- /dev/null +++ b/boost/atomic/detail/gcc_atomic_memory_order_utils.hpp @@ -0,0 +1,66 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/gcc_atomic_memory_order_utils.hpp + * + * This header contains utilities for working with gcc atomic memory order constants. + */ + +#ifndef BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +/*! + * The function converts \c boost::memory_order values to the compiler-specific constants. + * + * NOTE: The intention is that the function is optimized away by the compiler, and the + * compiler-specific constants are passed to the intrinsics. Unfortunately, constexpr doesn't + * work in this case because the standard atomics interface require memory ordering + * constants to be passed as function arguments, at which point they stop being constexpr. + * However, it is crucial that the compiler sees constants and not runtime values, + * because otherwise it just ignores the ordering value and always uses seq_cst. + * This is the case with Intel C++ Compiler 14.0.3 (Composer XE 2013 SP1, update 3) and + * gcc 4.8.2. Intel Compiler issues a warning in this case: + * + * warning #32013: Invalid memory order specified. Defaulting to seq_cst memory order. + * + * while gcc acts silently. + * + * To mitigate the problem ALL functions, including the atomic<> members must be + * declared with BOOST_FORCEINLINE. In this case the compilers are able to see that + * all functions are called with constant orderings and call intrinstcts properly. + * + * Unfortunately, this still doesn't work in debug mode as the compiler doesn't + * propagate constants even when functions are marked with BOOST_FORCEINLINE. In this case + * all atomic operaions will be executed with seq_cst semantics. + */ +BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT +{ + return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME : + (order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE : + (order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST))))); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_GCC_ATOMIC_MEMORY_ORDER_UTILS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/gcc_ppc_asm_common.hpp b/boost/atomic/detail/gcc_ppc_asm_common.hpp new file mode 100644 index 0000000..9eb119e --- /dev/null +++ b/boost/atomic/detail/gcc_ppc_asm_common.hpp @@ -0,0 +1,33 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/gcc_ppc_asm_common.hpp + * + * This header contains basic utilities for gcc asm-based PowerPC backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(_AIX) +#define BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL(label) label ":\n\t" +#define BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " " label "\n\t" +#else +// Standard assembler tool (as) on AIX does not support numeric jump labels, so we have to use offsets instead. +// https://github.com/boostorg/atomic/pull/50 +#define BOOST_ATOMIC_DETAIL_PPC_ASM_LABEL(label) +#define BOOST_ATOMIC_DETAIL_PPC_ASM_JUMP(insn, label, offset) insn " $" offset "\n\t" +#endif + +#endif // BOOST_ATOMIC_DETAIL_GCC_PPC_ASM_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/header.hpp b/boost/atomic/detail/header.hpp new file mode 100644 index 0000000..0251c61 --- /dev/null +++ b/boost/atomic/detail/header.hpp @@ -0,0 +1,72 @@ +/* + * Copyright Andrey Semashev 2020. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include + +#if !defined(BOOST_ATOMIC_ENABLE_WARNINGS) + +#if defined(BOOST_MSVC) + +#pragma warning(push, 3) +// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B' +#pragma warning(disable: 4251) +// non dll-interface class 'A' used as base for dll-interface class 'B' +#pragma warning(disable: 4275) +// 'this' : used in base member initializer list +#pragma warning(disable: 4355) +// 'int' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable: 4800) +// unreferenced formal parameter +#pragma warning(disable: 4100) +// conditional expression is constant +#pragma warning(disable: 4127) +// default constructor could not be generated +#pragma warning(disable: 4510) +// copy constructor could not be generated +#pragma warning(disable: 4511) +// assignment operator could not be generated +#pragma warning(disable: 4512) +// function marked as __forceinline not inlined +#pragma warning(disable: 4714) +// decorated name length exceeded, name was truncated +#pragma warning(disable: 4503) +// declaration of 'A' hides previous local declaration +#pragma warning(disable: 4456) +// declaration of 'A' hides global declaration +#pragma warning(disable: 4459) +// 'X': This function or variable may be unsafe. Consider using Y instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. +#pragma warning(disable: 4996) +// 'A' : multiple assignment operators specified +#pragma warning(disable: 4522) +// unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable: 4146) +// frame pointer register 'ebx' modified by inline assembly code +#pragma warning(disable: 4731) +// alignment is sensitive to packing +#pragma warning(disable: 4121) +// 'struct_name' : structure was padded due to __declspec(align()) +#pragma warning(disable: 4324) + +#elif defined(BOOST_GCC) && BOOST_GCC >= 40600 + +#pragma GCC diagnostic push +// unused parameter 'arg' +#pragma GCC diagnostic ignored "-Wunused-parameter" +// missing initializer for member var +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + +#elif defined(BOOST_CLANG) + +#pragma clang diagnostic push +// unused parameter 'arg' +#pragma clang diagnostic ignored "-Wunused-parameter" +// missing initializer for member var +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + +#endif + +#endif // !defined(BOOST_ATOMIC_ENABLE_WARNINGS) diff --git a/boost/atomic/detail/int_sizes.hpp b/boost/atomic/detail/int_sizes.hpp new file mode 100644 index 0000000..be250df --- /dev/null +++ b/boost/atomic/detail/int_sizes.hpp @@ -0,0 +1,164 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/int_sizes.hpp + * + * This header defines macros for testing buitin integer type sizes + */ + +#ifndef BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// GCC and compatible compilers define internal macros with builtin type traits +#if defined(__SIZEOF_SHORT__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT __SIZEOF_SHORT__ +#endif +#if defined(__SIZEOF_INT__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_INT __SIZEOF_INT__ +#endif +#if defined(__SIZEOF_LONG__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG __SIZEOF_LONG__ +#endif +#if defined(__SIZEOF_LONG_LONG__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG __SIZEOF_LONG_LONG__ +#endif +#if defined(__SIZEOF_WCHAR_T__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T __SIZEOF_WCHAR_T__ +#endif +#if defined(__SIZEOF_POINTER__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER __SIZEOF_POINTER__ +#elif defined(_MSC_VER) +#if defined(_M_AMD64) || defined(_M_ARM64) || defined(_M_IA64) +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 8 +#else +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 4 +#endif +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) + +// Try to deduce sizes from limits +#include +#if defined(__has_include) +#if __has_include() +#include +#endif +#endif +#include + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) +#if (USHRT_MAX + 0) == 0xff +#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 1 +#elif (USHRT_MAX + 0) == 0xffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 2 +#elif (USHRT_MAX + 0) == 0xffffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 4 +#elif (USHRT_MAX + 0) == UINT64_C(0xffffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_SHORT 8 +#endif +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) +#if (UINT_MAX + 0) == 0xff +#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 1 +#elif (UINT_MAX + 0) == 0xffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 2 +#elif (UINT_MAX + 0) == 0xffffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 4 +#elif (UINT_MAX + 0) == UINT64_C(0xffffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_INT 8 +#endif +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) +#if (ULONG_MAX + 0) == 0xff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 1 +#elif (ULONG_MAX + 0) == 0xffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 2 +#elif (ULONG_MAX + 0) == 0xffffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 4 +#elif (ULONG_MAX + 0) == UINT64_C(0xffffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LONG 8 +#endif +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) +#if defined(__hpux) // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 8 +#else + +// The list of the non-standard macros (the ones except ULLONG_MAX) is taken from cstdint.hpp +#if defined(ULLONG_MAX) +#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULLONG_MAX +#elif defined(ULONG_LONG_MAX) +#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULONG_LONG_MAX +#elif defined(ULONGLONG_MAX) +#define BOOST_ATOMIC_DETAIL_ULLONG_MAX ULONGLONG_MAX +#elif defined(_LLONG_MAX) // strangely enough, this one seems to be holding the limit for the unsigned integer +#define BOOST_ATOMIC_DETAIL_ULLONG_MAX _LLONG_MAX +#endif + +#if (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 1 +#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 2 +#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == 0xffffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 4 +#elif (BOOST_ATOMIC_DETAIL_ULLONG_MAX + 0) == UINT64_C(0xffffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_LLONG 8 +#endif + +#endif // defined(__hpux) +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && defined(UINTPTR_MAX) +#if (UINTPTR_MAX + 0) == 0xffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 2 +#elif (UINTPTR_MAX + 0) == 0xffffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 4 +#elif (UINTPTR_MAX + 0) == UINT64_C(0xffffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 8 +#endif +#endif // !defined(BOOST_ATOMIC_DETAIL_SIZEOF_POINTER) && defined(UINTPTR_MAX) + +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T) + +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER <= 1310 || defined(UNDER_CE) && _MSC_VER <= 1500) +// MSVC 7.1 and MSVC 8 (arm) define WCHAR_MAX to a value not suitable for constant expressions +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 2 +#elif (WCHAR_MAX + 0) == 0xff || (WCHAR_MAX + 0) == 0x7f +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 1 +#elif (WCHAR_MAX + 0) == 0xffff || (WCHAR_MAX + 0) == 0x7fff +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 2 +#elif (WCHAR_MAX + 0) == 0xffffffff || (WCHAR_MAX + 0) == 0x7fffffff +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 4 +#elif (WCHAR_MAX + 0) == UINT64_C(0xffffffffffffffff) || (WCHAR_MAX + 0) == INT64_C(0x7fffffffffffffff) +#define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T 8 +#endif +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) ||\ + !defined(BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T) +#error Boost.Atomic: Failed to determine builtin integer sizes, the target platform is not supported. Please, report to the developers (patches are welcome). +#endif + +#endif // BOOST_ATOMIC_DETAIL_INT_SIZES_HPP_INCLUDED_ diff --git a/boost/atomic/detail/integral_conversions.hpp b/boost/atomic/detail/integral_conversions.hpp new file mode 100644 index 0000000..c61a55a --- /dev/null +++ b/boost/atomic/detail/integral_conversions.hpp @@ -0,0 +1,108 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/integral_conversions.hpp + * + * This header defines sign/zero extension and truncation utilities for Boost.Atomic. The tools assume two's complement signed integer representation. + */ + +#ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Output, typename Input > +BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT +{ + // Note: If we are casting with truncation or to the same-sized output, don't cause signed integer overflow by this chain of conversions + return atomics::detail::bitwise_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Output >::type >( + static_cast< typename atomics::detail::make_unsigned< Input >::type >(input))); +} + +template< typename Output, typename Input > +BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT +{ + return static_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Input >::type >(input)); +} + +//! Zero-extends or truncates (wraps) input operand to fit in the output type +template< typename Output, typename Input > +BOOST_FORCEINLINE Output zero_extend(Input input) BOOST_NOEXCEPT +{ + return atomics::detail::zero_extend_impl< Output >(input, atomics::detail::integral_constant< bool, atomics::detail::is_signed< Output >::value >()); +} + +//! Truncates (wraps) input operand to fit in the output type +template< typename Output, typename Input > +BOOST_FORCEINLINE Output integral_truncate(Input input) BOOST_NOEXCEPT +{ + // zero_extend does the truncation + return atomics::detail::zero_extend< Output >(input); +} + +template< typename Output, typename Input > +BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT +{ + return atomics::detail::integral_truncate< Output >(input); +} + +template< typename Output, typename Input > +BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT +{ + return static_cast< Output >(atomics::detail::bitwise_cast< typename atomics::detail::make_signed< Input >::type >(input)); +} + +//! Sign-extends or truncates (wraps) input operand to fit in the output type +template< typename Output, typename Input > +BOOST_FORCEINLINE Output sign_extend(Input input) BOOST_NOEXCEPT +{ + return atomics::detail::sign_extend_impl< Output >(input, atomics::detail::integral_constant< bool, sizeof(Output) <= sizeof(Input) >()); +} + +//! Sign-extends or truncates (wraps) input operand to fit in the output type +template< typename Output, typename Input > +BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::true_type) BOOST_NOEXCEPT +{ + return atomics::detail::sign_extend< Output >(input); +} + +//! Zero-extends or truncates (wraps) input operand to fit in the output type +template< typename Output, typename Input > +BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::false_type) BOOST_NOEXCEPT +{ + return atomics::detail::zero_extend< Output >(input); +} + +//! Sign- or zero-extends or truncates (wraps) input operand to fit in the output type +template< bool Signed, typename Output, typename Input > +BOOST_FORCEINLINE Output integral_extend(Input input) BOOST_NOEXCEPT +{ + return atomics::detail::integral_extend< Output >(input, atomics::detail::integral_constant< bool, Signed >()); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/interlocked.hpp b/boost/atomic/detail/interlocked.hpp new file mode 100644 index 0000000..fff93e7 --- /dev/null +++ b/boost/atomic/detail/interlocked.hpp @@ -0,0 +1,546 @@ +#ifndef BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP +#define BOOST_ATOMIC_DETAIL_INTERLOCKED_HPP + +// Copyright (c) 2009 Helge Bahmann +// Copyright (c) 2012 - 2014, 2017 Andrey Semashev +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(_WIN32_WCE) + +#if _WIN32_WCE >= 0x600 + +extern "C" long __cdecl _InterlockedCompareExchange(long volatile*, long, long); +extern "C" long __cdecl _InterlockedExchangeAdd(long volatile*, long); +extern "C" long __cdecl _InterlockedExchange(long volatile*, long); +extern "C" long __cdecl _InterlockedIncrement(long volatile*); +extern "C" long __cdecl _InterlockedDecrement(long volatile*); + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest)) + +#else // _WIN32_WCE >= 0x600 + +extern "C" long __cdecl InterlockedCompareExchange(long*, long, long); +extern "C" long __cdecl InterlockedExchangeAdd(long*, long); +extern "C" long __cdecl InterlockedExchange(long*, long); +extern "C" long __cdecl InterlockedIncrement(long*); +extern "C" long __cdecl InterlockedDecrement(long*); + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), exchange, compare) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) InterlockedDecrement((long*)(dest)) + +#endif // _WIN32_WCE >= 0x600 + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), (long)(exchange), (long)(compare))) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE((long*)(dest), (long)(exchange))) + +#elif defined(_MSC_VER) && _MSC_VER >= 1310 + +#if _MSC_VER < 1400 + +extern "C" long __cdecl _InterlockedCompareExchange(long volatile*, long, long); +extern "C" long __cdecl _InterlockedExchangeAdd(long volatile*, long); +extern "C" long __cdecl _InterlockedExchange(long volatile*, long); +extern "C" long __cdecl _InterlockedIncrement(long volatile*); +extern "C" long __cdecl _InterlockedDecrement(long volatile*); + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange) +#pragma intrinsic(_InterlockedExchangeAdd) +#pragma intrinsic(_InterlockedExchange) +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedDecrement) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), exchange, compare) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest)) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE((long*)(dest), (long)(exchange), (long)(compare))) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, exchange) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE((long*)(dest), (long)(exchange))) + +#else // _MSC_VER < 1400 + +#include + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange) +#pragma intrinsic(_InterlockedExchangeAdd) +#pragma intrinsic(_InterlockedExchange) +#pragma intrinsic(_InterlockedIncrement) +#pragma intrinsic(_InterlockedDecrement) +#pragma intrinsic(_InterlockedAnd) +#pragma intrinsic(_InterlockedOr) +#pragma intrinsic(_InterlockedXor) +#pragma intrinsic(_interlockedbittestandset) +#pragma intrinsic(_interlockedbittestandreset) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) _InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) _InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) _InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) _InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) _InterlockedDecrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_AND(dest, arg) _InterlockedAnd((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR(dest, arg) _InterlockedOr((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR(dest, arg) _InterlockedXor((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTS(dest, arg) _interlockedbittestandset((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTR(dest, arg) _interlockedbittestandreset((long*)(dest), (long)(arg)) + +#if defined(_M_AMD64) +#if defined(BOOST_MSVC) +#pragma intrinsic(_interlockedbittestandset64) +#pragma intrinsic(_interlockedbittestandreset64) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_BTS64(dest, arg) _interlockedbittestandset64((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTR64(dest, arg) _interlockedbittestandreset64((__int64*)(dest), (__int64)(arg)) +#endif // defined(_M_AMD64) + +#if (defined(_M_IX86) && _M_IX86 >= 500) || defined(_M_AMD64) || defined(_M_IA64) +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange64) +#endif +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) _InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#endif + +#if _MSC_VER >= 1500 && defined(_M_AMD64) +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange128) +#endif +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE128(dest, exchange, compare) _InterlockedCompareExchange128((__int64*)(dest), ((const __int64*)(&exchange))[1], ((const __int64*)(&exchange))[0], (__int64*)(compare)) +#endif + +#if _MSC_VER >= 1600 + +// MSVC 2010 and later provide intrinsics for 8 and 16 bit integers. +// Note that for each bit count these macros must be either all defined or all not defined. +// Otherwise atomic<> operations will be implemented inconsistently. + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange8) +#pragma intrinsic(_InterlockedExchangeAdd8) +#pragma intrinsic(_InterlockedExchange8) +#pragma intrinsic(_InterlockedAnd8) +#pragma intrinsic(_InterlockedOr8) +#pragma intrinsic(_InterlockedXor8) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8(dest, exchange, compare) _InterlockedCompareExchange8((char*)(dest), (char)(exchange), (char)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8(dest, addend) _InterlockedExchangeAdd8((char*)(dest), (char)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(dest, newval) _InterlockedExchange8((char*)(dest), (char)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_AND8(dest, arg) _InterlockedAnd8((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR8(dest, arg) _InterlockedOr8((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR8(dest, arg) _InterlockedXor8((char*)(dest), (char)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange16) +#pragma intrinsic(_InterlockedExchangeAdd16) +#pragma intrinsic(_InterlockedExchange16) +#pragma intrinsic(_InterlockedAnd16) +#pragma intrinsic(_InterlockedOr16) +#pragma intrinsic(_InterlockedXor16) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16(dest, exchange, compare) _InterlockedCompareExchange16((short*)(dest), (short)(exchange), (short)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16(dest, addend) _InterlockedExchangeAdd16((short*)(dest), (short)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(dest, newval) _InterlockedExchange16((short*)(dest), (short)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_AND16(dest, arg) _InterlockedAnd16((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR16(dest, arg) _InterlockedOr16((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR16(dest, arg) _InterlockedXor16((short*)(dest), (short)(arg)) + +#endif // _MSC_VER >= 1600 + +#if defined(_M_AMD64) || defined(_M_IA64) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedExchangeAdd64) +#pragma intrinsic(_InterlockedExchange64) +#pragma intrinsic(_InterlockedAnd64) +#pragma intrinsic(_InterlockedOr64) +#pragma intrinsic(_InterlockedXor64) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) _InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) _InterlockedExchange64((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_AND64(dest, arg) _InterlockedAnd64((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR64(dest, arg) _InterlockedOr64((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR64(dest, arg) _InterlockedXor64((__int64*)(dest), (__int64)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchangePointer) +#pragma intrinsic(_InterlockedExchangePointer) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) _InterlockedExchangePointer((void**)(dest), (void*)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((long*)(dest), byte_offset)) + +#elif defined(_M_IX86) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)_InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare))) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)_InterlockedExchange((long*)(dest), (long)(newval))) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset)) + +#endif + +#if _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedExchangeAdd64) +#pragma intrinsic(_InterlockedExchange64) +#pragma intrinsic(_InterlockedAnd64) +#pragma intrinsic(_InterlockedOr64) +#pragma intrinsic(_InterlockedXor64) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) _InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) _InterlockedExchange64((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_AND64(dest, arg) _InterlockedAnd64((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR64(dest, arg) _InterlockedOr64((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR64(dest, arg) _InterlockedXor64((__int64*)(dest), (__int64)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedCompareExchange8_nf) +#pragma intrinsic(_InterlockedCompareExchange8_acq) +#pragma intrinsic(_InterlockedCompareExchange8_rel) +#pragma intrinsic(_InterlockedCompareExchange16_nf) +#pragma intrinsic(_InterlockedCompareExchange16_acq) +#pragma intrinsic(_InterlockedCompareExchange16_rel) +#pragma intrinsic(_InterlockedCompareExchange_nf) +#pragma intrinsic(_InterlockedCompareExchange_acq) +#pragma intrinsic(_InterlockedCompareExchange_rel) +#pragma intrinsic(_InterlockedCompareExchange64) +#pragma intrinsic(_InterlockedCompareExchange64_nf) +#pragma intrinsic(_InterlockedCompareExchange64_acq) +#pragma intrinsic(_InterlockedCompareExchange64_rel) +#pragma intrinsic(_InterlockedCompareExchangePointer) +#pragma intrinsic(_InterlockedCompareExchangePointer_nf) +#pragma intrinsic(_InterlockedCompareExchangePointer_acq) +#pragma intrinsic(_InterlockedCompareExchangePointer_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELAXED(dest, exchange, compare) _InterlockedCompareExchange8_nf((char*)(dest), (char)(exchange), (char)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange8_acq((char*)(dest), (char)(exchange), (char)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE8_RELEASE(dest, exchange, compare) _InterlockedCompareExchange8_rel((char*)(dest), (char)(exchange), (char)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELAXED(dest, exchange, compare) _InterlockedCompareExchange16_nf((short*)(dest), (short)(exchange), (short)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange16_acq((short*)(dest), (short)(exchange), (short)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE16_RELEASE(dest, exchange, compare) _InterlockedCompareExchange16_rel((short*)(dest), (short)(exchange), (short)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELAXED(dest, exchange, compare) _InterlockedCompareExchange_nf((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange_acq((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_RELEASE(dest, exchange, compare) _InterlockedCompareExchange_rel((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) _InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELAXED(dest, exchange, compare) _InterlockedCompareExchange64_nf((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchange64_acq((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64_RELEASE(dest, exchange, compare) _InterlockedCompareExchange64_rel((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) _InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_RELAXED(dest, exchange, compare) _InterlockedCompareExchangePointer_nf((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_ACQUIRE(dest, exchange, compare) _InterlockedCompareExchangePointer_acq((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER_RELEASE(dest, exchange, compare) _InterlockedCompareExchangePointer_rel((void**)(dest), (void*)(exchange), (void*)(compare)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedExchangeAdd8_nf) +#pragma intrinsic(_InterlockedExchangeAdd8_acq) +#pragma intrinsic(_InterlockedExchangeAdd8_rel) +#pragma intrinsic(_InterlockedExchangeAdd16_nf) +#pragma intrinsic(_InterlockedExchangeAdd16_acq) +#pragma intrinsic(_InterlockedExchangeAdd16_rel) +#pragma intrinsic(_InterlockedExchangeAdd_nf) +#pragma intrinsic(_InterlockedExchangeAdd_acq) +#pragma intrinsic(_InterlockedExchangeAdd_rel) +#pragma intrinsic(_InterlockedExchangeAdd64_nf) +#pragma intrinsic(_InterlockedExchangeAdd64_acq) +#pragma intrinsic(_InterlockedExchangeAdd64_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELAXED(dest, addend) _InterlockedExchangeAdd8_nf((char*)(dest), (char)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_ACQUIRE(dest, addend) _InterlockedExchangeAdd8_acq((char*)(dest), (char)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD8_RELEASE(dest, addend) _InterlockedExchangeAdd8_rel((char*)(dest), (char)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELAXED(dest, addend) _InterlockedExchangeAdd16_nf((short*)(dest), (short)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_ACQUIRE(dest, addend) _InterlockedExchangeAdd16_acq((short*)(dest), (short)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD16_RELEASE(dest, addend) _InterlockedExchangeAdd16_rel((short*)(dest), (short)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED(dest, addend) _InterlockedExchangeAdd_nf((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE(dest, addend) _InterlockedExchangeAdd_acq((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE(dest, addend) _InterlockedExchangeAdd_rel((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED(dest, addend) _InterlockedExchangeAdd64_nf((__int64*)(dest), (__int64)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE(dest, addend) _InterlockedExchangeAdd64_acq((__int64*)(dest), (__int64)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE(dest, addend) _InterlockedExchangeAdd64_rel((__int64*)(dest), (__int64)(addend)) + +#if defined(_M_ARM64) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64((__int64*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELAXED((__int64*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_ACQUIRE((__int64*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64_RELEASE((__int64*)(dest), byte_offset)) +#else +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD((long*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELAXED(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELAXED((long*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_ACQUIRE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_ACQUIRE((long*)(dest), byte_offset)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER_RELEASE(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_RELEASE((long*)(dest), byte_offset)) +#endif + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedExchange8_nf) +#pragma intrinsic(_InterlockedExchange8_acq) +#pragma intrinsic(_InterlockedExchange16_nf) +#pragma intrinsic(_InterlockedExchange16_acq) +#pragma intrinsic(_InterlockedExchange_nf) +#pragma intrinsic(_InterlockedExchange_acq) +#pragma intrinsic(_InterlockedExchange64_nf) +#pragma intrinsic(_InterlockedExchange64_acq) +#pragma intrinsic(_InterlockedExchangePointer) +#pragma intrinsic(_InterlockedExchangePointer_nf) +#pragma intrinsic(_InterlockedExchangePointer_acq) +#if _MSC_VER >= 1800 +#pragma intrinsic(_InterlockedExchange8_rel) +#pragma intrinsic(_InterlockedExchange16_rel) +#pragma intrinsic(_InterlockedExchange_rel) +#pragma intrinsic(_InterlockedExchange64_rel) +#pragma intrinsic(_InterlockedExchangePointer_rel) +#endif +#endif + +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELAXED(dest, newval) _InterlockedExchange8_nf((char*)(dest), (char)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_ACQUIRE(dest, newval) _InterlockedExchange8_acq((char*)(dest), (char)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELAXED(dest, newval) _InterlockedExchange16_nf((short*)(dest), (short)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_ACQUIRE(dest, newval) _InterlockedExchange16_acq((short*)(dest), (short)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELAXED(dest, newval) _InterlockedExchange_nf((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ACQUIRE(dest, newval) _InterlockedExchange_acq((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELAXED(dest, newval) _InterlockedExchange64_nf((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_ACQUIRE(dest, newval) _InterlockedExchange64_acq((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) _InterlockedExchangePointer((void**)(dest), (void*)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELAXED(dest, newval) _InterlockedExchangePointer_nf((void**)(dest), (void*)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_ACQUIRE(dest, newval) _InterlockedExchangePointer_acq((void**)(dest), (void*)(newval)) + +#if _MSC_VER >= 1800 +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(dest, newval) _InterlockedExchange8_rel((char*)(dest), (char)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(dest, newval) _InterlockedExchange16_rel((short*)(dest), (short)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(dest, newval) _InterlockedExchange_rel((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(dest, newval) _InterlockedExchange64_rel((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELEASE(dest, newval) _InterlockedExchangePointer_rel((void**)(dest), (void*)(newval)) +#else +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE8_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE8(dest, newval) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE16_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE16(dest, newval) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER_RELEASE(dest, newval) BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) +#endif + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedAnd8_nf) +#pragma intrinsic(_InterlockedAnd8_acq) +#pragma intrinsic(_InterlockedAnd8_rel) +#pragma intrinsic(_InterlockedAnd16_nf) +#pragma intrinsic(_InterlockedAnd16_acq) +#pragma intrinsic(_InterlockedAnd16_rel) +#pragma intrinsic(_InterlockedAnd_nf) +#pragma intrinsic(_InterlockedAnd_acq) +#pragma intrinsic(_InterlockedAnd_rel) +#pragma intrinsic(_InterlockedAnd64_nf) +#pragma intrinsic(_InterlockedAnd64_acq) +#pragma intrinsic(_InterlockedAnd64_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_AND8_RELAXED(dest, arg) _InterlockedAnd8_nf((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND8_ACQUIRE(dest, arg) _InterlockedAnd8_acq((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND8_RELEASE(dest, arg) _InterlockedAnd8_rel((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND16_RELAXED(dest, arg) _InterlockedAnd16_nf((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND16_ACQUIRE(dest, arg) _InterlockedAnd16_acq((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND16_RELEASE(dest, arg) _InterlockedAnd16_rel((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND_RELAXED(dest, arg) _InterlockedAnd_nf((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND_ACQUIRE(dest, arg) _InterlockedAnd_acq((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND_RELEASE(dest, arg) _InterlockedAnd_rel((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND64_RELAXED(dest, arg) _InterlockedAnd64_nf((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND64_ACQUIRE(dest, arg) _InterlockedAnd64_acq((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_AND64_RELEASE(dest, arg) _InterlockedAnd64_rel((__int64*)(dest), (__int64)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedOr8_nf) +#pragma intrinsic(_InterlockedOr8_acq) +#pragma intrinsic(_InterlockedOr8_rel) +#pragma intrinsic(_InterlockedOr16_nf) +#pragma intrinsic(_InterlockedOr16_acq) +#pragma intrinsic(_InterlockedOr16_rel) +#pragma intrinsic(_InterlockedOr_nf) +#pragma intrinsic(_InterlockedOr_acq) +#pragma intrinsic(_InterlockedOr_rel) +#pragma intrinsic(_InterlockedOr64_nf) +#pragma intrinsic(_InterlockedOr64_acq) +#pragma intrinsic(_InterlockedOr64_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_OR8_RELAXED(dest, arg) _InterlockedOr8_nf((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR8_ACQUIRE(dest, arg) _InterlockedOr8_acq((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR8_RELEASE(dest, arg) _InterlockedOr8_rel((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR16_RELAXED(dest, arg) _InterlockedOr16_nf((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR16_ACQUIRE(dest, arg) _InterlockedOr16_acq((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR16_RELEASE(dest, arg) _InterlockedOr16_rel((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR_RELAXED(dest, arg) _InterlockedOr_nf((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR_ACQUIRE(dest, arg) _InterlockedOr_acq((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR_RELEASE(dest, arg) _InterlockedOr_rel((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR64_RELAXED(dest, arg) _InterlockedOr64_nf((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR64_ACQUIRE(dest, arg) _InterlockedOr64_acq((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_OR64_RELEASE(dest, arg) _InterlockedOr64_rel((__int64*)(dest), (__int64)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_InterlockedXor8_nf) +#pragma intrinsic(_InterlockedXor8_acq) +#pragma intrinsic(_InterlockedXor8_rel) +#pragma intrinsic(_InterlockedXor16_nf) +#pragma intrinsic(_InterlockedXor16_acq) +#pragma intrinsic(_InterlockedXor16_rel) +#pragma intrinsic(_InterlockedXor_nf) +#pragma intrinsic(_InterlockedXor_acq) +#pragma intrinsic(_InterlockedXor_rel) +#pragma intrinsic(_InterlockedXor64_nf) +#pragma intrinsic(_InterlockedXor64_acq) +#pragma intrinsic(_InterlockedXor64_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_XOR8_RELAXED(dest, arg) _InterlockedXor8_nf((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR8_ACQUIRE(dest, arg) _InterlockedXor8_acq((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR8_RELEASE(dest, arg) _InterlockedXor8_rel((char*)(dest), (char)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR16_RELAXED(dest, arg) _InterlockedXor16_nf((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR16_ACQUIRE(dest, arg) _InterlockedXor16_acq((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR16_RELEASE(dest, arg) _InterlockedXor16_rel((short*)(dest), (short)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR_RELAXED(dest, arg) _InterlockedXor_nf((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR_ACQUIRE(dest, arg) _InterlockedXor_acq((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR_RELEASE(dest, arg) _InterlockedXor_rel((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR64_RELAXED(dest, arg) _InterlockedXor64_nf((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR64_ACQUIRE(dest, arg) _InterlockedXor64_acq((__int64*)(dest), (__int64)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_XOR64_RELEASE(dest, arg) _InterlockedXor64_rel((__int64*)(dest), (__int64)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_interlockedbittestandset_nf) +#pragma intrinsic(_interlockedbittestandset_acq) +#pragma intrinsic(_interlockedbittestandset_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_BTS_RELAXED(dest, arg) _interlockedbittestandset_nf((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTS_ACQUIRE(dest, arg) _interlockedbittestandset_acq((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTS_RELEASE(dest, arg) _interlockedbittestandset_rel((long*)(dest), (long)(arg)) + +#if defined(BOOST_MSVC) +#pragma intrinsic(_interlockedbittestandreset_nf) +#pragma intrinsic(_interlockedbittestandreset_acq) +#pragma intrinsic(_interlockedbittestandreset_rel) +#endif + +#define BOOST_ATOMIC_INTERLOCKED_BTR_RELAXED(dest, arg) _interlockedbittestandreset_nf((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTR_ACQUIRE(dest, arg) _interlockedbittestandreset_acq((long*)(dest), (long)(arg)) +#define BOOST_ATOMIC_INTERLOCKED_BTR_RELEASE(dest, arg) _interlockedbittestandreset_rel((long*)(dest), (long)(arg)) + +#endif // _MSC_VER >= 1700 && defined(_M_ARM) + +#endif // _MSC_VER < 1400 + +#else // defined(_MSC_VER) && _MSC_VER >= 1310 + +#if defined(BOOST_USE_WINDOWS_H) + +#include + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) InterlockedDecrement((long*)(dest)) + +#if defined(_WIN64) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) InterlockedExchange64((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend)) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) InterlockedExchangePointer((void**)(dest), (void*)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset)) + +#else // defined(_WIN64) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset)) + +#endif // defined(_WIN64) + +#else // defined(BOOST_USE_WINDOWS_H) + +#if defined(__MINGW64__) +#define BOOST_ATOMIC_INTERLOCKED_IMPORT +#else +#define BOOST_ATOMIC_INTERLOCKED_IMPORT __declspec(dllimport) +#endif + +namespace boost { +namespace atomics { +namespace detail { + +extern "C" { + +BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedCompareExchange(long volatile*, long, long); +BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchange(long volatile*, long); +BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedExchangeAdd(long volatile*, long); +BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedIncrement(long volatile*, long); +BOOST_ATOMIC_INTERLOCKED_IMPORT long __stdcall InterlockedDecrement(long volatile*, long); + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange((long*)(dest), (long)(exchange), (long)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval) boost::atomics::detail::InterlockedExchange((long*)(dest), (long)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, addend) boost::atomics::detail::InterlockedExchangeAdd((long*)(dest), (long)(addend)) +#define BOOST_ATOMIC_INTERLOCKED_INCREMENT(dest) boost::atomics::detail::InterlockedIncrement((long*)(dest)) +#define BOOST_ATOMIC_INTERLOCKED_DECREMENT(dest) boost::atomics::detail::InterlockedDecrement((long*)(dest)) + +#if defined(_WIN64) + +BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedCompareExchange64(__int64 volatile*, __int64, __int64); +BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchange64(__int64 volatile*, __int64); +BOOST_ATOMIC_INTERLOCKED_IMPORT __int64 __stdcall InterlockedExchangeAdd64(__int64 volatile*, __int64); + +BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedCompareExchangePointer(void* volatile*, void*, void*); +BOOST_ATOMIC_INTERLOCKED_IMPORT void* __stdcall InterlockedExchangePointer(void* volatile*, void*); + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE64(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchange64((__int64*)(dest), (__int64)(exchange), (__int64)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE64(dest, newval) boost::atomics::detail::InterlockedExchange64((__int64*)(dest), (__int64)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, addend) boost::atomics::detail::InterlockedExchangeAdd64((__int64*)(dest), (__int64)(addend)) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) boost::atomics::detail::InterlockedCompareExchangePointer((void**)(dest), (void*)(exchange), (void*)(compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) boost::atomics::detail::InterlockedExchangePointer((void**)(dest), (void*)(newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD64(dest, byte_offset)) + +#else // defined(_WIN64) + +#define BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE_POINTER(dest, exchange, compare) ((void*)BOOST_ATOMIC_INTERLOCKED_COMPARE_EXCHANGE(dest, exchange, compare)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_POINTER(dest, newval) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE(dest, newval)) +#define BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD_POINTER(dest, byte_offset) ((void*)BOOST_ATOMIC_INTERLOCKED_EXCHANGE_ADD(dest, byte_offset)) + +#endif // defined(_WIN64) + +} // extern "C" + +} // namespace detail +} // namespace atomics +} // namespace boost + +#undef BOOST_ATOMIC_INTERLOCKED_IMPORT + +#endif // defined(BOOST_USE_WINDOWS_H) + +#endif // defined(_MSC_VER) + +#endif diff --git a/boost/atomic/detail/intptr.hpp b/boost/atomic/detail/intptr.hpp new file mode 100644 index 0000000..e8e30c7 --- /dev/null +++ b/boost/atomic/detail/intptr.hpp @@ -0,0 +1,46 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/intptr.hpp + * + * This header defines (u)intptr_t types. + */ + +#ifndef BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_ + +#include +#if defined(BOOST_HAS_INTPTR_T) +#include +#endif +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_HAS_INTPTR_T) +using boost::uintptr_t; +using boost::intptr_t; +#else +typedef std::size_t uintptr_t; +typedef std::ptrdiff_t intptr_t; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_INTPTR_HPP_INCLUDED_ diff --git a/boost/atomic/detail/link.hpp b/boost/atomic/detail/link.hpp new file mode 100644 index 0000000..4f522ac --- /dev/null +++ b/boost/atomic/detail/link.hpp @@ -0,0 +1,58 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2012 Hartmut Kaiser + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/config.hpp + * + * This header defines macros for linking with compiled library of Boost.Atomic + */ + +#ifndef BOOST_ATOMIC_DETAIL_LINK_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_LINK_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Set up dll import/export options +#if (defined(BOOST_ATOMIC_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && \ + !defined(BOOST_ATOMIC_STATIC_LINK) + +#if defined(BOOST_ATOMIC_SOURCE) +#define BOOST_ATOMIC_DECL BOOST_SYMBOL_EXPORT +#define BOOST_ATOMIC_BUILD_DLL +#else +#define BOOST_ATOMIC_DECL BOOST_SYMBOL_IMPORT +#endif + +#endif // building a shared library + +#ifndef BOOST_ATOMIC_DECL +#define BOOST_ATOMIC_DECL +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Auto library naming +#if !defined(BOOST_ATOMIC_SOURCE) && !defined(BOOST_ALL_NO_LIB) && \ + !defined(BOOST_ATOMIC_NO_LIB) + +#define BOOST_LIB_NAME boost_atomic + +// tell the auto-link code to select a dll when required: +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ATOMIC_DYN_LINK) +#define BOOST_DYN_LINK +#endif + +#include + +#endif // auto-linking disabled + +#endif diff --git a/boost/atomic/detail/lock_pool.hpp b/boost/atomic/detail/lock_pool.hpp new file mode 100644 index 0000000..64b66a2 --- /dev/null +++ b/boost/atomic/detail/lock_pool.hpp @@ -0,0 +1,151 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2011 Helge Bahmann + * Copyright (c) 2013-2014, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/lock_pool.hpp + * + * This header contains declaration of the lock pool used to emulate atomic ops. + */ + +#ifndef BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_ + +#include +#include +#include +#include +#if defined(BOOST_WINDOWS) +#include +#elif defined(BOOST_HAS_NANOSLEEP) +#include +#else +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +BOOST_FORCEINLINE void wait_some() BOOST_NOEXCEPT +{ +#if defined(BOOST_WINDOWS) + boost::winapi::SwitchToThread(); +#elif defined(BOOST_HAS_NANOSLEEP) + // Do not use sched_yield or pthread_yield as at least on Linux it doesn't block the thread if there are no other + // pending threads on the current CPU. Proper sleeping is guaranteed to block the thread, which allows other threads + // to potentially migrate to this CPU and complete the tasks we're waiting for. + struct ::timespec ts = {}; + ts.tv_sec = 0; + ts.tv_nsec = 1000; + ::nanosleep(&ts, NULL); +#else + ::usleep(1); +#endif +} + +namespace lock_pool { + +BOOST_ATOMIC_DECL void* short_lock(atomics::detail::uintptr_t h) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void* long_lock(atomics::detail::uintptr_t h) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void unlock(void* ls) BOOST_NOEXCEPT; + +BOOST_ATOMIC_DECL void* allocate_wait_state(void* ls, const volatile void* addr) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void free_wait_state(void* ls, void* ws) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void wait(void* ls, void* ws) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void notify_one(void* ls, const volatile void* addr) BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void notify_all(void* ls, const volatile void* addr) BOOST_NOEXCEPT; + +BOOST_ATOMIC_DECL void thread_fence() BOOST_NOEXCEPT; +BOOST_ATOMIC_DECL void signal_fence() BOOST_NOEXCEPT; + +template< std::size_t Alignment > +BOOST_FORCEINLINE atomics::detail::uintptr_t hash_ptr(const volatile void* addr) BOOST_NOEXCEPT +{ + atomics::detail::uintptr_t ptr = (atomics::detail::uintptr_t)addr; + atomics::detail::uintptr_t h = ptr / Alignment; + + // Since many malloc/new implementations return pointers with higher alignment + // than indicated by Alignment, it makes sense to mix higher bits + // into the lower ones. On 64-bit platforms, malloc typically aligns to 16 bytes, + // on 32-bit - to 8 bytes. + BOOST_CONSTEXPR_OR_CONST std::size_t malloc_alignment = sizeof(void*) >= 8u ? 16u : 8u; + BOOST_IF_CONSTEXPR (Alignment != malloc_alignment) + h ^= ptr / malloc_alignment; + + return h; +} + +template< std::size_t Alignment, bool LongLock = false > +class scoped_lock +{ +private: + void* m_lock; + +public: + explicit scoped_lock(const volatile void* addr) BOOST_NOEXCEPT + { + atomics::detail::uintptr_t h = lock_pool::hash_ptr< Alignment >(addr); + BOOST_IF_CONSTEXPR (!LongLock) + m_lock = lock_pool::short_lock(h); + else + m_lock = lock_pool::long_lock(h); + } + ~scoped_lock() BOOST_NOEXCEPT + { + lock_pool::unlock(m_lock); + } + + void* get_lock_state() const BOOST_NOEXCEPT + { + return m_lock; + } + + BOOST_DELETED_FUNCTION(scoped_lock(scoped_lock const&)) + BOOST_DELETED_FUNCTION(scoped_lock& operator=(scoped_lock const&)) +}; + +template< std::size_t Alignment > +class scoped_wait_state : + public scoped_lock< Alignment, true > +{ +private: + void* m_wait_state; + +public: + explicit scoped_wait_state(const volatile void* addr) BOOST_NOEXCEPT : + scoped_lock< Alignment, true >(addr) + { + m_wait_state = lock_pool::allocate_wait_state(this->get_lock_state(), addr); + } + ~scoped_wait_state() BOOST_NOEXCEPT + { + lock_pool::free_wait_state(this->get_lock_state(), m_wait_state); + } + + void wait() BOOST_NOEXCEPT + { + lock_pool::wait(this->get_lock_state(), m_wait_state); + } + + BOOST_DELETED_FUNCTION(scoped_wait_state(scoped_wait_state const&)) + BOOST_DELETED_FUNCTION(scoped_wait_state& operator=(scoped_wait_state const&)) +}; + +} // namespace lock_pool +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_LOCK_POOL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/memory_order_utils.hpp b/boost/atomic/detail/memory_order_utils.hpp new file mode 100644 index 0000000..6f6ab75 --- /dev/null +++ b/boost/atomic/detail/memory_order_utils.hpp @@ -0,0 +1,47 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/memory_order_utils.hpp + * + * This header contains utilities related to memory order constants. + */ + +#ifndef BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order deduce_failure_order(memory_order order) BOOST_NOEXCEPT +{ + return order == memory_order_acq_rel ? memory_order_acquire : (order == memory_order_release ? memory_order_relaxed : order); +} + +BOOST_FORCEINLINE BOOST_CONSTEXPR bool cas_failure_order_must_not_be_stronger_than_success_order(memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT +{ + // 15 == (memory_order_seq_cst | memory_order_consume), see memory_order.hpp + // Given the enum values we can test the strength of memory order requirements with this single condition. + return (static_cast< unsigned int >(failure_order) & 15u) <= (static_cast< unsigned int >(success_order) & 15u); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_MEMORY_ORDER_UTILS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/once_flag.hpp b/boost/atomic/detail/once_flag.hpp new file mode 100644 index 0000000..45bfd2f --- /dev/null +++ b/boost/atomic/detail/once_flag.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/once_flag.hpp + * + * This header declares \c once_flag structure for controlling one time initialization + */ + +#ifndef BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_ + +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +typedef atomics::detail::core_operations< 1u, false, false > once_flag_operations; + +struct once_flag +{ + BOOST_ATOMIC_DETAIL_ALIGNED_VAR(once_flag_operations::storage_alignment, once_flag_operations::storage_type, m_flag); +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_ONCE_FLAG_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_gcc_aarch32_common.hpp b/boost/atomic/detail/ops_gcc_aarch32_common.hpp new file mode 100644 index 0000000..c963931 --- /dev/null +++ b/boost/atomic/detail/ops_gcc_aarch32_common.hpp @@ -0,0 +1,53 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_aarch32_common.hpp + * + * This header contains basic utilities for gcc AArch32 backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH32_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH32_COMMON_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_DETAIL_AARCH32_MO_SWITCH(mo)\ + switch (mo)\ + {\ + case memory_order_relaxed:\ + BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN("r", "r")\ + break;\ + \ + case memory_order_consume:\ + case memory_order_acquire:\ + BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN("a", "r")\ + break;\ + \ + case memory_order_release:\ + BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN("r", "l")\ + break;\ + \ + default:\ + BOOST_ATOMIC_DETAIL_AARCH32_MO_INSN("a", "l")\ + break;\ + } + +#if defined(BOOST_ATOMIC_DETAIL_AARCH32_LITTLE_ENDIAN) +#define BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(arg) "%" BOOST_STRINGIZE(arg) +#define BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(arg) "%H" BOOST_STRINGIZE(arg) +#else +#define BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_LO(arg) "%H" BOOST_STRINGIZE(arg) +#define BOOST_ATOMIC_DETAIL_AARCH32_ASM_ARG_HI(arg) "%" BOOST_STRINGIZE(arg) +#endif + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH32_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_gcc_aarch64_common.hpp b/boost/atomic/detail/ops_gcc_aarch64_common.hpp new file mode 100644 index 0000000..80c26af --- /dev/null +++ b/boost/atomic/detail/ops_gcc_aarch64_common.hpp @@ -0,0 +1,53 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_aarch64_common.hpp + * + * This header contains basic utilities for gcc AArch64 backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH64_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH64_COMMON_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_DETAIL_AARCH64_MO_SWITCH(mo)\ + switch (mo)\ + {\ + case memory_order_relaxed:\ + BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN("", "")\ + break;\ + \ + case memory_order_consume:\ + case memory_order_acquire:\ + BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN("a", "")\ + break;\ + \ + case memory_order_release:\ + BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN("", "l")\ + break;\ + \ + default:\ + BOOST_ATOMIC_DETAIL_AARCH64_MO_INSN("a", "l")\ + break;\ + } + +#if defined(BOOST_ATOMIC_DETAIL_AARCH64_LITTLE_ENDIAN) +#define BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "0" +#define BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "1" +#else +#define BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_LO "1" +#define BOOST_ATOMIC_DETAIL_AARCH64_ASM_ARG_HI "0" +#endif + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_AARCH64_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_gcc_arm_common.hpp b/boost/atomic/detail/ops_gcc_arm_common.hpp new file mode 100644 index 0000000..08046a9 --- /dev/null +++ b/boost/atomic/detail/ops_gcc_arm_common.hpp @@ -0,0 +1,63 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_arm_common.hpp + * + * This header contains basic utilities for gcc ARM backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +struct core_arch_operations_gcc_arm_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + fence_arch_operations::hardware_full_fence(); + } + + static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + fence_arch_operations::hardware_full_fence(); + } + + static BOOST_FORCEINLINE void fence_after_store(memory_order order) BOOST_NOEXCEPT + { + if (order == memory_order_seq_cst) + fence_arch_operations::hardware_full_fence(); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ARM_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_gcc_ppc_common.hpp b/boost/atomic/detail/ops_gcc_ppc_common.hpp new file mode 100644 index 0000000..0bf4553 --- /dev/null +++ b/boost/atomic/detail/ops_gcc_ppc_common.hpp @@ -0,0 +1,73 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2013 Tim Blechmann + * Copyright (c) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_ppc_common.hpp + * + * This header contains basic utilities for gcc PowerPC backend. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +// The implementation below uses information from this document: +// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2010.02.19a.html + +// A note about memory_order_consume. Technically, this architecture allows to avoid +// unnecessary memory barrier after consume load since it supports data dependency ordering. +// However, some compiler optimizations may break a seemingly valid code relying on data +// dependency tracking by injecting bogus branches to aid out of order execution. +// This may happen not only in Boost.Atomic code but also in user's code, which we have no +// control of. See this thread: http://lists.boost.org/Archives/boost/2014/06/213890.php. +// For this reason we promote memory_order_consume to memory_order_acquire. + +struct core_arch_operations_gcc_ppc_base +{ + static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; + static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = true; + + static BOOST_FORCEINLINE void fence_before(memory_order order) BOOST_NOEXCEPT + { +#if defined(__powerpc64__) || defined(__PPC64__) + if (order == memory_order_seq_cst) + __asm__ __volatile__ ("sync" ::: "memory"); + else if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __asm__ __volatile__ ("lwsync" ::: "memory"); +#else + if ((static_cast< unsigned int >(order) & static_cast< unsigned int >(memory_order_release)) != 0u) + __asm__ __volatile__ ("sync" ::: "memory"); +#endif + } + + static BOOST_FORCEINLINE void fence_after(memory_order order) BOOST_NOEXCEPT + { + if ((static_cast< unsigned int >(order) & (static_cast< unsigned int >(memory_order_consume) | static_cast< unsigned int >(memory_order_acquire))) != 0u) + __asm__ __volatile__ ("isync" ::: "memory"); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_PPC_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/ops_msvc_common.hpp b/boost/atomic/detail/ops_msvc_common.hpp new file mode 100644 index 0000000..ef9c0ab --- /dev/null +++ b/boost/atomic/detail/ops_msvc_common.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2014, 2019 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_msvc_common.hpp + * + * This header contains common tools for MSVC implementation of the atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Define compiler barriers +#if defined(__INTEL_COMPILER) +#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() __memory_barrier() +#elif defined(__clang__) +#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() __atomic_signal_fence(__ATOMIC_SEQ_CST) +#elif defined(_MSC_VER) && !defined(_WIN32_WCE) +extern "C" void _ReadWriteBarrier(void); +#pragma intrinsic(_ReadWriteBarrier) +#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() _ReadWriteBarrier() +#endif + +#ifndef BOOST_ATOMIC_DETAIL_COMPILER_BARRIER +#define BOOST_ATOMIC_DETAIL_COMPILER_BARRIER() +#endif + +#include + +#endif // BOOST_ATOMIC_DETAIL_OPS_MSVC_COMMON_HPP_INCLUDED_ diff --git a/boost/atomic/detail/pause.hpp b/boost/atomic/detail/pause.hpp new file mode 100644 index 0000000..efdfb62 --- /dev/null +++ b/boost/atomic/detail/pause.hpp @@ -0,0 +1,61 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * (C) Copyright 2013 Tim Blechmann + * (C) Copyright 2013, 2020 Andrey Semashev + */ + +#ifndef BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(_MSC_VER) +#if defined(_M_AMD64) || defined(_M_IX86) +extern "C" void _mm_pause(void); +#if defined(BOOST_MSVC) +#pragma intrinsic(_mm_pause) +#endif +#elif defined(_M_ARM64) || defined(_M_ARM) +extern "C" void __yield(void); +#if defined(BOOST_MSVC) +#pragma intrinsic(__yield) +#endif +#endif +#endif + +namespace boost { +namespace atomics { +namespace detail { + +BOOST_FORCEINLINE void pause() BOOST_NOEXCEPT +{ +#if defined(_MSC_VER) +#if defined(_M_AMD64) || defined(_M_IX86) + _mm_pause(); +#elif defined(_M_ARM64) || defined(_M_ARM) + __yield(); +#endif +#elif defined(__GNUC__) +#if defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__("pause;" : : : "memory"); +#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__) || defined(__aarch64__) + __asm__ __volatile__("yield;" : : : "memory"); +#endif +#endif +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_PAUSE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/platform.hpp b/boost/atomic/detail/platform.hpp new file mode 100644 index 0000000..8260958 --- /dev/null +++ b/boost/atomic/detail/platform.hpp @@ -0,0 +1,209 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2014-2018, 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/platform.hpp + * + * This header defines macros for the target platform detection + */ + +#ifndef BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__GNUC__) && defined(__arm__) + +// Newer gcc versions define __ARM_ARCH. Older ones don't, so we have to deduce ARM arch version from a bunch of version-specific macros. +#if defined(__ARM_ARCH) +#define BOOST_ATOMIC_DETAIL_ARM_ARCH __ARM_ARCH +#elif defined(__ARM_ARCH_8A__) +#define BOOST_ATOMIC_DETAIL_ARM_ARCH 8 +#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) ||\ + defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ||\ + defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7S__) +#define BOOST_ATOMIC_DETAIL_ARM_ARCH 7 +#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) ||\ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) ||\ + defined(__ARM_ARCH_6ZK__) +#define BOOST_ATOMIC_DETAIL_ARM_ARCH 6 +#else +// We are not interested in older versions - they don't support atomic ops +#define BOOST_ATOMIC_DETAIL_ARM_ARCH 0 +#endif + +#endif // defined(__GNUC__) && defined(__arm__) + +#if !defined(BOOST_ATOMIC_FORCE_FALLBACK) + +// Determine the target platform. +// The target platform describes the compiler and target architecture. It can be used by more generic backends, such as the ones +// based on compiler intrinsics, to implement specialized operations in a non-generic way. + +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_x86 +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_x86 + +#elif defined(__GNUC__) && defined(__aarch64__) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_aarch64 +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_aarch64 + +#elif defined(__GNUC__) && defined(__arm__) && (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 6) + +#if (BOOST_ATOMIC_DETAIL_ARM_ARCH >= 8) +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_aarch32 +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_aarch32 +#else +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_arm +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_arm +#endif + +#elif defined(__GNUC__) && (defined(__POWERPC__) || defined(__PPC__)) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_ppc +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND gcc_ppc + +#elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__sparcv8plus) || defined(__sparc_v9__)) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_sparc + +#elif defined(__GNUC__) && defined(__alpha__) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND gcc_alpha + +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND msvc_x86 + +#elif defined(_MSC_VER) && _MSC_VER >= 1700 && (defined(_M_ARM) || defined(_M_ARM64)) + +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND msvc_arm + +#endif + +// Compiler-based backends + +// IBM XL C++ Compiler has to be checked before GCC/Clang as it pretends to be one but does not support __atomic* intrinsics. +// It does support GCC inline assembler though. +#if !(defined(__ibmxl__) || defined(__IBMCPP__)) &&\ + ((defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 407)) ||\ + (defined(BOOST_CLANG) && ((__clang_major__ * 100 + __clang_minor__) >= 302))) &&\ + (\ + (__GCC_ATOMIC_BOOL_LOCK_FREE == 2) ||\ + (__GCC_ATOMIC_CHAR_LOCK_FREE == 2) ||\ + (__GCC_ATOMIC_SHORT_LOCK_FREE == 2) ||\ + (__GCC_ATOMIC_INT_LOCK_FREE == 2) ||\ + (__GCC_ATOMIC_LONG_LOCK_FREE == 2) ||\ + (__GCC_ATOMIC_LLONG_LOCK_FREE == 2)\ + ) + +#define BOOST_ATOMIC_DETAIL_CORE_BACKEND gcc_atomic + +// GCC __sync* instrinsics backend is less efficient than asm-based backends, so use it only when nothing better is available. +#elif !defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND) &&\ + defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 401) &&\ + (\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1) ||\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2) ||\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) ||\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) ||\ + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)\ + ) + +#define BOOST_ATOMIC_DETAIL_CORE_BACKEND gcc_sync + +#endif + +// OS-based backends + +#if !defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND) && !defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND) + +#if defined(__linux__) && defined(__arm__) + +#define BOOST_ATOMIC_DETAIL_CORE_BACKEND linux_arm + +#elif defined(BOOST_WINDOWS) || defined(_WIN32_CE) + +#define BOOST_ATOMIC_DETAIL_CORE_BACKEND windows + +#endif + +#endif // !defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND) + +// Waiting and notifying operations backends +#if defined(BOOST_WINDOWS) + +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND windows + +#else // defined(BOOST_WINDOWS) + +#include + +#if defined(BOOST_ATOMIC_DETAIL_HAS_FUTEX) +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND futex +#elif defined(__APPLE__) +#if !defined(BOOST_ATOMIC_NO_DARWIN_ULOCK) && (\ + (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000)) +// Darwin 16+ supports ulock API +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND darwin_ulock +#endif // __ENVIRONMENT_*_VERSION_MIN_REQUIRED__ +#elif defined(__FreeBSD__) +#include +// FreeBSD prior to 7.0 had _umtx_op with a different signature +#if defined(__FreeBSD_version) && __FreeBSD_version >= 700000 +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND freebsd_umtx +#endif // defined(__FreeBSD_version) && __FreeBSD_version >= 700000 +#elif defined(__DragonFly__) +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND dragonfly_umtx +#endif + +#endif // defined(BOOST_WINDOWS) + +#endif // !defined(BOOST_ATOMIC_FORCE_FALLBACK) + +#if !defined(BOOST_ATOMIC_DETAIL_FP_BACKEND) +#define BOOST_ATOMIC_DETAIL_FP_BACKEND generic +#define BOOST_ATOMIC_DETAIL_FP_BACKEND_GENERIC +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_BACKEND) +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND generic +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_GENERIC +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND) +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND generic +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_GENERIC +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_WAIT_BACKEND) +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND generic +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND_GENERIC +#endif + +#if defined(BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND) +#define BOOST_ATOMIC_DETAIL_CORE_ARCH_BACKEND_HEADER(prefix) +#endif +#if defined(BOOST_ATOMIC_DETAIL_CORE_BACKEND) +#define BOOST_ATOMIC_DETAIL_CORE_BACKEND_HEADER(prefix) +#endif +#define BOOST_ATOMIC_DETAIL_FP_BACKEND_HEADER(prefix) +#define BOOST_ATOMIC_DETAIL_EXTRA_BACKEND_HEADER(prefix) +#define BOOST_ATOMIC_DETAIL_EXTRA_FP_BACKEND_HEADER(prefix) +#define BOOST_ATOMIC_DETAIL_WAIT_BACKEND_HEADER(prefix) + +#endif // BOOST_ATOMIC_DETAIL_PLATFORM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/storage_traits.hpp b/boost/atomic/detail/storage_traits.hpp new file mode 100644 index 0000000..1ba9d8f --- /dev/null +++ b/boost/atomic/detail/storage_traits.hpp @@ -0,0 +1,187 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2013 - 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/storage_traits.hpp + * + * This header defines underlying types used as storage + */ + +#ifndef BOOST_ATOMIC_DETAIL_STORAGE_TRAITS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_STORAGE_TRAITS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T > +BOOST_FORCEINLINE void non_atomic_load(T const volatile& from, T& to) BOOST_NOEXCEPT +{ + to = from; +} + +template< std::size_t Size, std::size_t Alignment = 1u > +struct BOOST_ATOMIC_DETAIL_MAY_ALIAS buffer_storage +{ + typedef unsigned char data_type[Size]; + BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(Alignment, data_type, data); + + BOOST_FORCEINLINE bool operator! () const BOOST_NOEXCEPT + { + return (data[0] == 0u && BOOST_ATOMIC_DETAIL_MEMCMP(data, data + 1, Size - 1u) == 0); + } + + BOOST_FORCEINLINE bool operator== (buffer_storage const& that) const BOOST_NOEXCEPT + { + return BOOST_ATOMIC_DETAIL_MEMCMP(data, that.data, Size) == 0; + } + + BOOST_FORCEINLINE bool operator!= (buffer_storage const& that) const BOOST_NOEXCEPT + { + return BOOST_ATOMIC_DETAIL_MEMCMP(data, that.data, Size) != 0; + } +}; + +template< std::size_t Size, std::size_t Alignment > +BOOST_FORCEINLINE void non_atomic_load(buffer_storage< Size, Alignment > const volatile& from, buffer_storage< Size, Alignment >& to) BOOST_NOEXCEPT +{ + BOOST_ATOMIC_DETAIL_MEMCPY(to.data, const_cast< unsigned char const* >(from.data), Size); +} + +template< std::size_t Size > +struct storage_traits +{ + typedef buffer_storage< Size, 1u > type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = 1u; + + // By default, prefer the maximum supported alignment + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 16u; +}; + +template< > +struct storage_traits< 1u > +{ + typedef boost::uint8_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = 1u; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 1u; +}; + +template< > +struct storage_traits< 2u > +{ + typedef boost::uint16_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = atomics::detail::alignment_of< boost::uint16_t >::value; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 2u; +}; + +template< > +struct storage_traits< 4u > +{ + typedef boost::uint32_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = atomics::detail::alignment_of< boost::uint32_t >::value; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 4u; +}; + +template< > +struct storage_traits< 8u > +{ + typedef boost::uint64_t BOOST_ATOMIC_DETAIL_MAY_ALIAS type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = atomics::detail::alignment_of< boost::uint64_t >::value; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 8u; +}; + +#if defined(BOOST_HAS_INT128) + +template< > +struct storage_traits< 16u > +{ + typedef boost::uint128_type BOOST_ATOMIC_DETAIL_MAY_ALIAS type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = atomics::detail::alignment_of< boost::uint128_type >::value; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 16u; +}; + +#else + +#if (__cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)) &&\ + (!defined(BOOST_GCC_VERSION) || BOOST_GCC_VERSION >= 40900) +using std::max_align_t; +#else + +#if defined(BOOST_MSVC) +#pragma warning(push) +// alignment is sensitive to packing +#pragma warning(disable: 4121) +#endif + +class max_align_helper; +union max_align_t +{ + void* ptr; + void (*fun_ptr)(); + int max_align_helper::*mem_ptr; + void (max_align_helper::*mem_fun_ptr)(); + long long ll; + long double ld; +#if defined(BOOST_HAS_INT128) + boost::int128_type i128; +#endif +#if defined(BOOST_HAS_FLOAT128) + boost::float128_type f128; +#endif +}; + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) + +template< > +struct storage_traits< 16u > +{ + typedef buffer_storage< 16u, atomics::detail::alignment_of< atomics::detail::max_align_t >::value > type; + + static BOOST_CONSTEXPR_OR_CONST std::size_t native_alignment = atomics::detail::alignment_of< atomics::detail::max_align_t >::value; + static BOOST_CONSTEXPR_OR_CONST std::size_t alignment = 16u; +}; + +#endif + +template< typename T > +struct storage_size_of +{ + static BOOST_CONSTEXPR_OR_CONST std::size_t size = sizeof(T); + static BOOST_CONSTEXPR_OR_CONST std::size_t value = (size == 3u ? 4u : (size >= 5u && size <= 7u ? 8u : (size >= 9u && size <= 15u ? 16u : size))); +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_STORAGE_TRAITS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/string_ops.hpp b/boost/atomic/detail/string_ops.hpp new file mode 100644 index 0000000..ce145b9 --- /dev/null +++ b/boost/atomic/detail/string_ops.hpp @@ -0,0 +1,61 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/string_ops.hpp + * + * This header defines string operations for Boost.Atomic + */ + +#ifndef BOOST_ATOMIC_DETAIL_STRING_OPS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_STRING_OPS_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__has_builtin) +#if __has_builtin(__builtin_memcpy) +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY +#endif +#if __has_builtin(__builtin_memcmp) +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP +#endif +#if __has_builtin(__builtin_memset) +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMSET +#endif +#elif defined(BOOST_GCC) +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP +#define BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMSET +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY) +#define BOOST_ATOMIC_DETAIL_MEMCPY __builtin_memcpy +#else +#define BOOST_ATOMIC_DETAIL_MEMCPY std::memcpy +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP) +#define BOOST_ATOMIC_DETAIL_MEMCMP __builtin_memcmp +#else +#define BOOST_ATOMIC_DETAIL_MEMCMP std::memcmp +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMSET) +#define BOOST_ATOMIC_DETAIL_MEMSET __builtin_memset +#else +#define BOOST_ATOMIC_DETAIL_MEMSET std::memset +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCPY) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMCMP) || !defined(BOOST_ATOMIC_DETAIL_HAS_BUILTIN_MEMSET) +#include +#endif + +#endif // BOOST_ATOMIC_DETAIL_STRING_OPS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/alignment_of.hpp b/boost/atomic/detail/type_traits/alignment_of.hpp new file mode 100644 index 0000000..bc5431f --- /dev/null +++ b/boost/atomic/detail/type_traits/alignment_of.hpp @@ -0,0 +1,51 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/alignment_of.hpp + * + * This header defines \c alignment_of type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_ALIGNMENT_OF_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_ALIGNMENT_OF_HPP_INCLUDED_ + +#include + +#if defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) ||\ + (defined(BOOST_GCC) && BOOST_GCC < 80100) ||\ + (defined(BOOST_CLANG) && !defined(__apple_build_version__) && __clang_major__ < 9) ||\ + (defined(BOOST_CLANG) && defined(__apple_build_version__) && __clang_major__ < 10) +// For some compilers std::alignment_of gives the wrong result for 64-bit types on 32-bit targets +#define BOOST_ATOMIC_DETAIL_NO_CXX11_STD_ALIGNMENT_OF +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_STD_ALIGNMENT_OF) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_STD_ALIGNMENT_OF) +using std::alignment_of; +#else +using boost::alignment_of; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_ALIGNMENT_OF_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/conditional.hpp b/boost/atomic/detail/type_traits/conditional.hpp new file mode 100644 index 0000000..6b9e896 --- /dev/null +++ b/boost/atomic/detail/type_traits/conditional.hpp @@ -0,0 +1,42 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/conditional.hpp + * + * This header defines \c conditional type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +using std::conditional; +#else +using boost::conditional; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/has_unique_object_representations.hpp b/boost/atomic/detail/type_traits/has_unique_object_representations.hpp new file mode 100644 index 0000000..bdd10f9 --- /dev/null +++ b/boost/atomic/detail/type_traits/has_unique_object_representations.hpp @@ -0,0 +1,143 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/has_unique_object_representations.hpp + * + * This header defines \c has_unique_object_representations type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if (defined(__cpp_lib_has_unique_object_representations) && __cpp_lib_has_unique_object_representations >= 201606) || \ + (defined(_CPPLIB_VER) && _CPPLIB_VER >= 650 && defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141 && defined(_HAS_CXX17) && _HAS_CXX17 != 0) + +namespace boost { +namespace atomics { +namespace detail { + +using std::has_unique_object_representations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#else // defined(__cpp_lib_has_unique_object_representations) ... + +#if (defined(__GNUC__) && __GNUC__ >= 7) || (defined(BOOST_MSVC) && BOOST_MSVC >= 1929) || \ + (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900) +#define BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS(x) __has_unique_object_representations(x) +#elif defined(__is_identifier) +#if !__is_identifier(__has_unique_object_representations) +#define BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS(x) __has_unique_object_representations(x) +#endif +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS) + +#include +#include + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T > +struct has_unique_object_representations : + public atomics::detail::integral_constant< bool, BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS(T) > +{ +}; + +template< typename T > +struct has_unique_object_representations< T[] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T, std::size_t N > +struct has_unique_object_representations< T[N] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< const T > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< volatile T > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< const volatile T > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< const T[] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< volatile T[] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T > +struct has_unique_object_representations< const volatile T[] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T, std::size_t N > +struct has_unique_object_representations< const T[N] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T, std::size_t N > +struct has_unique_object_representations< volatile T[N] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +template< typename T, std::size_t N > +struct has_unique_object_representations< const volatile T[N] > : + public atomics::detail::has_unique_object_representations< T > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#else // defined(BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS) + +#define BOOST_ATOMIC_DETAIL_NO_HAS_UNIQUE_OBJECT_REPRESENTATIONS + +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_UNIQUE_OBJECT_REPRESENTATIONS) + +#endif // defined(__cpp_lib_has_unique_object_representations) ... + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_HAS_UNIQUE_OBJECT_REPRESENTATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/integral_constant.hpp b/boost/atomic/detail/type_traits/integral_constant.hpp new file mode 100644 index 0000000..eac8649 --- /dev/null +++ b/boost/atomic/detail/type_traits/integral_constant.hpp @@ -0,0 +1,46 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/integral_constant.hpp + * + * This header defines \c integral_constant wrapper + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +using std::integral_constant; +using std::true_type; +using std::false_type; +#else +using boost::integral_constant; +using boost::true_type; +using boost::false_type; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_enum.hpp b/boost/atomic/detail/type_traits/is_enum.hpp new file mode 100644 index 0000000..16ff3be --- /dev/null +++ b/boost/atomic/detail/type_traits/is_enum.hpp @@ -0,0 +1,42 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_enum.hpp + * + * This header defines \c is_enum type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_ENUM_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_ENUM_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +using std::is_enum; +#else +using boost::is_enum; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_ENUM_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_floating_point.hpp b/boost/atomic/detail/type_traits/is_floating_point.hpp new file mode 100644 index 0000000..46e2ab8 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_floating_point.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_floating_point.hpp + * + * This header defines \c is_floating_point type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FLOATING_POINT_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FLOATING_POINT_HPP_INCLUDED_ + +#include +// Some versions of libstdc++ don't consider __float128 a floating point type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_FLOAT128) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_FLOAT128) +using std::is_floating_point; +#else +using boost::is_floating_point; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FLOATING_POINT_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_function.hpp b/boost/atomic/detail/type_traits/is_function.hpp new file mode 100644 index 0000000..e720535 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_function.hpp @@ -0,0 +1,42 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_function.hpp + * + * This header defines \c is_function type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +using std::is_function; +#else +using boost::is_function; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_iec559.hpp b/boost/atomic/detail/type_traits/is_iec559.hpp new file mode 100644 index 0000000..299c4f0 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_iec559.hpp @@ -0,0 +1,47 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_iec559.hpp + * + * This header defines \c is_iec559 type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_IEC559_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_IEC559_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename T > +struct is_iec559 +{ + static BOOST_CONSTEXPR_OR_CONST bool value = !!std::numeric_limits< T >::is_iec559; +}; + +#if defined(BOOST_HAS_FLOAT128) +// libstdc++ does not specialize numeric_limits for __float128 +template< > +struct is_iec559< boost::float128_type > +{ + static BOOST_CONSTEXPR_OR_CONST bool value = true; +}; +#endif // defined(BOOST_HAS_FLOAT128) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_IEC559_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_integral.hpp b/boost/atomic/detail/type_traits/is_integral.hpp new file mode 100644 index 0000000..ef3e2e3 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_integral.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_integral.hpp + * + * This header defines \c is_integral type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ + +#include +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::is_integral; +#else +using boost::is_integral; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_INTEGRAL_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp b/boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp new file mode 100644 index 0000000..bc8f6ee --- /dev/null +++ b/boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp @@ -0,0 +1,46 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_nothrow_default_constructible.hpp + * + * This header defines \c is_nothrow_default_constructible type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ + +#include +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +using std::is_nothrow_default_constructible; +#elif !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template< typename T > +using is_nothrow_default_constructible = boost::has_nothrow_constructor< T >; +#else +template< typename T > +struct is_nothrow_default_constructible : public boost::has_nothrow_constructor< T > {}; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_signed.hpp b/boost/atomic/detail/type_traits/is_signed.hpp new file mode 100644 index 0000000..2dc1df7 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_signed.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_signed.hpp + * + * This header defines \c is_signed type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ + +#include +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::is_signed; +#else +using boost::is_signed; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_SIGNED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_trivially_copyable.hpp b/boost/atomic/detail/type_traits/is_trivially_copyable.hpp new file mode 100644 index 0000000..7323212 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_trivially_copyable.hpp @@ -0,0 +1,45 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_trivially_copyable.hpp + * + * This header defines \c is_trivially_copyable type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED_ + +#include +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#else +// For std::is_trivially_copyable we require a genuine support from the compiler. +// Fallback to is_pod or a false negative result in Boost.TypeTraits is not acceptable +// as this trait will be used in a static assert and may deny valid uses of boost::atomic/atomic_ref. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE) + +namespace boost { +namespace atomics { +namespace detail { + +using std::is_trivially_copyable; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE) + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_COPYABLE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp b/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp new file mode 100644 index 0000000..5f88b88 --- /dev/null +++ b/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp @@ -0,0 +1,46 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_trivially_default_constructible.hpp + * + * This header defines \c is_trivially_default_constructible type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ + +#include +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +using std::is_trivially_default_constructible; +#elif !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template< typename T > +using is_trivially_default_constructible = boost::has_trivial_constructor< T >; +#else +template< typename T > +struct is_trivially_default_constructible : public boost::has_trivial_constructor< T > {}; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/make_signed.hpp b/boost/atomic/detail/type_traits/make_signed.hpp new file mode 100644 index 0000000..82f61b3 --- /dev/null +++ b/boost/atomic/detail/type_traits/make_signed.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/make_signed.hpp + * + * This header defines \c make_signed type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ + +#include +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::make_signed; +#else +using boost::make_signed; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_SIGNED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/make_unsigned.hpp b/boost/atomic/detail/type_traits/make_unsigned.hpp new file mode 100644 index 0000000..573a161 --- /dev/null +++ b/boost/atomic/detail/type_traits/make_unsigned.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2017 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/make_unsigned.hpp + * + * This header defines \c make_unsigned type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_UNSIGNED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_UNSIGNED_HPP_INCLUDED_ + +#include +// Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +using std::make_unsigned; +#else +using boost::make_unsigned; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_MAKE_UNSIGNED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/type_traits/remove_cv.hpp b/boost/atomic/detail/type_traits/remove_cv.hpp new file mode 100644 index 0000000..4462179 --- /dev/null +++ b/boost/atomic/detail/type_traits/remove_cv.hpp @@ -0,0 +1,42 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2023 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/remove_cv.hpp + * + * This header defines \c remove_cv type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_REMOVE_CV_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_REMOVE_CV_HPP_INCLUDED_ + +#include +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) +using std::remove_cv; +#else +using boost::remove_cv; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_REMOVE_CV_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_capabilities.hpp b/boost/atomic/detail/wait_capabilities.hpp new file mode 100644 index 0000000..d9137b0 --- /dev/null +++ b/boost/atomic/detail/wait_capabilities.hpp @@ -0,0 +1,363 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_capabilities.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPABILITIES_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPABILITIES_HPP_INCLUDED_ + +#include +#include +#include +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) +#include +#endif + +#if !defined(BOOST_ATOMIC_EMULATED) && !defined(BOOST_ATOMIC_DETAIL_WAIT_BACKEND_GENERIC) +#include BOOST_ATOMIC_DETAIL_WAIT_BACKEND_HEADER(boost/atomic/detail/wait_caps_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY 0 +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY 0 +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY 0 +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY 0 +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY 0 +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY 0 +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY 0 +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY 0 +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT128_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT128_WAIT_NOTIFY 0 +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT128_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_INT128_IPC_WAIT_NOTIFY 0 +#endif + + +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR8_T_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR8_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR8_T_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR8_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR16_T_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR16_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR16_T_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR16_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR32_T_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR32_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_CHAR32_T_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_CHAR32_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 1 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 2 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 4 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T == 8 +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_WCHAR_T_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 1 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_SHORT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_SHORT_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 +#define BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_INT_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_INT == 1 +#define BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_INT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_INT_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LONG_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 1 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LONG_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY +#if BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 1 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LLONG == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LLONG_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_POINTER_WAIT_NOTIFY +#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8 +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4 +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_WAIT_NOTIFY 0 +#endif +#endif + +#define BOOST_ATOMIC_HAS_NATIVE_ADDRESS_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_POINTER_WAIT_NOTIFY + +#ifndef BOOST_ATOMIC_HAS_NATIVE_POINTER_IPC_WAIT_NOTIFY +#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8 +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4 +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_POINTER_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#define BOOST_ATOMIC_HAS_NATIVE_ADDRESS_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_POINTER_IPC_WAIT_NOTIFY + +// We store bools in 1-byte storage in all backends +#ifndef BOOST_ATOMIC_HAS_NATIVE_BOOL_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_BOOL_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_BOOL_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_BOOL_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT8_IPC_WAIT_NOTIFY +#endif + +#ifndef BOOST_ATOMIC_HAS_NATIVE_FLAG_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_FLAG_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#endif +#ifndef BOOST_ATOMIC_HAS_NATIVE_FLAG_IPC_WAIT_NOTIFY +#define BOOST_ATOMIC_HAS_NATIVE_FLAG_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#endif + +#if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) +#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_WAIT_NOTIFY 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT) +#if BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 2 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 4 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT == 8 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_FLOAT <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_FLOAT_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_WAIT_NOTIFY 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 2 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 4 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE == 8 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_DOUBLE <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_DOUBLE_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_WAIT_NOTIFY 0 +#endif +#endif + +#if !defined(BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY) && defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE) +#if BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 2 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT16_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 4 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE == 8 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY +#elif BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE > 8 && BOOST_ATOMIC_DETAIL_SIZEOF_LONG_DOUBLE <= 16 +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY BOOST_ATOMIC_HAS_NATIVE_INT128_IPC_WAIT_NOTIFY +#else +#define BOOST_ATOMIC_HAS_NATIVE_LONG_DOUBLE_IPC_WAIT_NOTIFY 0 +#endif +#endif + +#endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPABILITIES_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_caps_darwin_ulock.hpp b/boost/atomic/detail/wait_caps_darwin_ulock.hpp new file mode 100644 index 0000000..45c0ccb --- /dev/null +++ b/boost/atomic/detail/wait_caps_darwin_ulock.hpp @@ -0,0 +1,58 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_caps_darwin_ulock.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPS_DARWIN_ULOCK_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPS_DARWIN_ULOCK_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE + +// Darwin 19+ (Mac OS 10.15+, iOS 13.0+, tvOS 13.0+, watchOS 6.0+) adds support for 64-bit +// and inter-process ulock operations. +// https://shift.click/blog/futex-like-apis/#darwin-macos-ios-tvos-watchos-and-more +// https://github.com/thomcc/ulock-sys/blob/2597e63cc5372459a903c292a3919d385a3e3789/src/lib.rs +#if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000) +#define BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64 +#define BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED +#endif + +// Darwin 20+ (Mac OS 11.0+, iOS 14.0+, tvOS 14.0+, watchOS 7.0+) introduces __ulock_wait2, which accepts +// the timeout in nanoseconds. __ulock_wait is a wrapper on top of __ulock_wait2. +#if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70000) +#define BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_WAIT2 +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#define BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) +#define BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY BOOST_ATOMIC_INT64_LOCK_FREE +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#define BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT64_LOCK_FREE +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPS_DARWIN_ULOCK_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_caps_dragonfly_umtx.hpp b/boost/atomic/detail/wait_caps_dragonfly_umtx.hpp new file mode 100644 index 0000000..7e9b54f --- /dev/null +++ b/boost/atomic/detail/wait_caps_dragonfly_umtx.hpp @@ -0,0 +1,30 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_caps_dragonfly_umtx.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPS_DRAGONFLY_UMTX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPS_DRAGONFLY_UMTX_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// DragonFly BSD umtx_sleep/umtx_wakeup use physical address to the atomic object as a key, which means it should support address-free operations. +// https://man.dragonflybsd.org/?command=umtx§ion=2 + +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPS_DRAGONFLY_UMTX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_caps_freebsd_umtx.hpp b/boost/atomic/detail/wait_caps_freebsd_umtx.hpp new file mode 100644 index 0000000..5f4359c --- /dev/null +++ b/boost/atomic/detail/wait_caps_freebsd_umtx.hpp @@ -0,0 +1,40 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_caps_freebsd_umtx.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPS_FREEBSD_UMTX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPS_FREEBSD_UMTX_HPP_INCLUDED_ + +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// FreeBSD _umtx_op uses physical address to the atomic object as a key, which means it should support address-free operations. +// https://www.freebsd.org/cgi/man.cgi?query=_umtx_op&apropos=0&sektion=2&manpath=FreeBSD+11-current&format=html + +#if (defined(UMTX_OP_WAIT_UINT) && BOOST_ATOMIC_DETAIL_SIZEOF_INT == 4) ||\ + (defined(UMTX_OP_WAIT) && BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 4) +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#endif + +#if defined(UMTX_OP_WAIT) && BOOST_ATOMIC_DETAIL_SIZEOF_LONG == 8 +#define BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY BOOST_ATOMIC_INT64_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT64_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT64_LOCK_FREE +#endif + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPS_FREEBSD_UMTX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_caps_futex.hpp b/boost/atomic/detail/wait_caps_futex.hpp new file mode 100644 index 0000000..e61d62b --- /dev/null +++ b/boost/atomic/detail/wait_caps_futex.hpp @@ -0,0 +1,31 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_caps_futex.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPS_FUTEX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPS_FUTEX_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_ATOMIC_DETAIL_HAS_FUTEX) +// futexes are always 32-bit and they always supported address-free operations +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT32_IPC_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_FUTEX) + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPS_FUTEX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_caps_windows.hpp b/boost/atomic/detail/wait_caps_windows.hpp new file mode 100644 index 0000000..a3c065a --- /dev/null +++ b/boost/atomic/detail/wait_caps_windows.hpp @@ -0,0 +1,57 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_caps_windows.hpp + * + * This header defines waiting/notifying operations capabilities macros. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_CAPS_WINDOWS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_CAPS_WINDOWS_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// MSDN says WaitOnAddress, WakeByAddressSingle and WakeByAddressAll only support notifications between threads of the same process, so no address-free operations. +// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress +// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddresssingle +// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddressall + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM) + +#define BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS + +#define BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY BOOST_ATOMIC_INT8_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY BOOST_ATOMIC_INT16_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY BOOST_ATOMIC_INT32_LOCK_FREE +#define BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY BOOST_ATOMIC_INT64_LOCK_FREE + +#else // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM) + +// Since we'll detect availability of WaitOnAddress etc. at run time, we have to define capability macros to 1 instead of 2 +#if BOOST_ATOMIC_INT8_LOCK_FREE > 0 +#define BOOST_ATOMIC_HAS_NATIVE_INT8_WAIT_NOTIFY 1 +#endif +#if BOOST_ATOMIC_INT16_LOCK_FREE > 0 +#define BOOST_ATOMIC_HAS_NATIVE_INT16_WAIT_NOTIFY 1 +#endif +#if BOOST_ATOMIC_INT32_LOCK_FREE > 0 +#define BOOST_ATOMIC_HAS_NATIVE_INT32_WAIT_NOTIFY 1 +#endif +#if BOOST_ATOMIC_INT64_LOCK_FREE > 0 +#define BOOST_ATOMIC_HAS_NATIVE_INT64_WAIT_NOTIFY 1 +#endif + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM) + +#endif // BOOST_ATOMIC_DETAIL_WAIT_CAPS_WINDOWS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_on_address.hpp b/boost/atomic/detail/wait_on_address.hpp new file mode 100644 index 0000000..a09734f --- /dev/null +++ b/boost/atomic/detail/wait_on_address.hpp @@ -0,0 +1,65 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_on_address.hpp + * + * This header contains declaration of runtime detection of \c WaitOnAddress and related APIs on Windows. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_ON_ADDRESS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_ON_ADDRESS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +typedef boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +wait_on_address_t( + volatile boost::winapi::VOID_* addr, + boost::winapi::PVOID_ compare_addr, + boost::winapi::SIZE_T_ size, + boost::winapi::DWORD_ timeout_ms); + +typedef boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +wake_by_address_t(boost::winapi::PVOID_ addr); + +extern BOOST_ATOMIC_DECL wait_on_address_t* wait_on_address; +extern BOOST_ATOMIC_DECL wake_by_address_t* wake_by_address_single; +extern BOOST_ATOMIC_DECL wake_by_address_t* wake_by_address_all; + +extern BOOST_ATOMIC_DECL once_flag wait_functions_once_flag; +BOOST_ATOMIC_DECL void initialize_wait_functions() BOOST_NOEXCEPT; + +BOOST_FORCEINLINE void ensure_wait_functions_initialized() BOOST_NOEXCEPT +{ + BOOST_STATIC_ASSERT_MSG(once_flag_operations::is_always_lock_free, "Boost.Atomic unsupported target platform: native atomic operations not implemented for bytes"); + if (BOOST_LIKELY(once_flag_operations::load(wait_functions_once_flag.m_flag, boost::memory_order_acquire) == 0u)) + return; + + initialize_wait_functions(); +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_ON_ADDRESS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_operations.hpp b/boost/atomic/detail/wait_operations.hpp new file mode 100644 index 0000000..d9d1b6b --- /dev/null +++ b/boost/atomic/detail/wait_operations.hpp @@ -0,0 +1,28 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_operations.hpp + * + * This header defines waiting/notifying atomic operations, including the generic version. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_HPP_INCLUDED_ + +#include +#include + +#if !defined(BOOST_ATOMIC_DETAIL_WAIT_BACKEND_GENERIC) +#include BOOST_ATOMIC_DETAIL_WAIT_BACKEND_HEADER(boost/atomic/detail/wait_ops_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_operations_fwd.hpp b/boost/atomic/detail/wait_operations_fwd.hpp new file mode 100644 index 0000000..1870af7 --- /dev/null +++ b/boost/atomic/detail/wait_operations_fwd.hpp @@ -0,0 +1,43 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_operations_fwd.hpp + * + * This header contains forward declaration of the \c wait_operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_FWD_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_FWD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< + typename Base, + std::size_t Size = sizeof(typename Base::storage_type), + bool AlwaysLockFree = Base::is_always_lock_free, + bool Interprocess = Base::is_interprocess +> +struct wait_operations; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPERATIONS_FWD_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_darwin_ulock.hpp b/boost/atomic/detail/wait_ops_darwin_ulock.hpp new file mode 100644 index 0000000..ae37880 --- /dev/null +++ b/boost/atomic/detail/wait_ops_darwin_ulock.hpp @@ -0,0 +1,158 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2021 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_darwin_ulock.hpp + * + * This header contains implementation of the waiting/notifying atomic operations based on Darwin systems using ulock syscalls. + * + * https://github.com/apple/darwin-xnu/blob/master/bsd/sys/ulock.h + * https://github.com/apple/darwin-xnu/blob/master/bsd/kern/sys_ulock.c + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_DARWIN_ULOCK_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_DARWIN_ULOCK_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +extern "C" { +// Timeout is in microseconds with zero meaning no timeout +int __ulock_wait(uint32_t operation, void* addr, uint64_t value, uint32_t timeout); +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_WAIT2) +// Timeout is in nanoseconds with zero meaning no timeout +int __ulock_wait2(uint32_t operation, void* addr, uint64_t value, uint64_t timeout, uint64_t value2); +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_WAIT2) +int __ulock_wake(uint32_t operation, void* addr, uint64_t wake_value); +} // extern "C" + +enum ulock_op +{ + ulock_op_compare_and_wait = 1, +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + ulock_op_compare_and_wait_shared = 3, +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) + ulock_op_compare_and_wait64 = 5, +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + ulock_op_compare_and_wait64_shared = 6, +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) + + // Flags for __ulock_wake + ulock_flag_wake_all = 0x00000100, + + // Generic flags + ulock_flag_no_errno = 0x01000000 +}; + +template< typename Base, uint32_t Opcode > +struct wait_operations_darwin_ulock_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_WAIT2) + __ulock_wait2(Opcode | ulock_flag_no_errno, const_cast< storage_type* >(&storage), old_val, 0u, 0u); +#else + __ulock_wait(Opcode | ulock_flag_no_errno, const_cast< storage_type* >(&storage), old_val, 0u); +#endif + new_val = base_type::load(storage, order); + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + while (true) + { + const int res = __ulock_wake(Opcode | ulock_flag_no_errno, const_cast< storage_type* >(&storage), 0u); + if (BOOST_LIKELY(res != -EINTR)) + break; + } + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + while (true) + { + const int res = __ulock_wake(Opcode | ulock_flag_wake_all | ulock_flag_no_errno, const_cast< storage_type* >(&storage), 0u); + if (BOOST_LIKELY(res != -EINTR)) + break; + } + } +}; + +template< typename Base > +struct wait_operations< Base, sizeof(uint32_t), true, false > : + public wait_operations_darwin_ulock_common< Base, ulock_op_compare_and_wait > +{ +}; + +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + +template< typename Base > +struct wait_operations< Base, sizeof(uint32_t), true, true > : + public wait_operations_darwin_ulock_common< Base, ulock_op_compare_and_wait_shared > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) + +template< typename Base > +struct wait_operations< Base, sizeof(uint64_t), true, false > : + public wait_operations_darwin_ulock_common< Base, ulock_op_compare_and_wait64 > +{ +}; + +#if defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) + +template< typename Base > +struct wait_operations< Base, sizeof(uint64_t), true, true > : + public wait_operations_darwin_ulock_common< Base, ulock_op_compare_and_wait64_shared > +{ +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK_SHARED) +#endif // defined(BOOST_ATOMIC_DETAIL_HAS_DARWIN_ULOCK64) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_DARWIN_ULOCK_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_dragonfly_umtx.hpp b/boost/atomic/detail/wait_ops_dragonfly_umtx.hpp new file mode 100644 index 0000000..466adbd --- /dev/null +++ b/boost/atomic/detail/wait_ops_dragonfly_umtx.hpp @@ -0,0 +1,75 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_dragonfly_umtx.hpp + * + * This header contains implementation of the waiting/notifying atomic operations based on DragonFly BSD umtx. + * https://man.dragonflybsd.org/?command=umtx§ion=2 + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_DRAGONFLY_UMTX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_DRAGONFLY_UMTX_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base, bool Interprocess > +struct wait_operations< Base, sizeof(int), true, Interprocess > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + ::umtx_sleep(reinterpret_cast< int* >(const_cast< storage_type* >(&storage)), static_cast< int >(old_val), 0); + new_val = base_type::load(storage, order); + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + ::umtx_wakeup(reinterpret_cast< int* >(const_cast< storage_type* >(&storage)), 1); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + ::umtx_wakeup(reinterpret_cast< int* >(const_cast< storage_type* >(&storage)), 0); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_DRAGONFLY_UMTX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_emulated.hpp b/boost/atomic/detail/wait_ops_emulated.hpp new file mode 100644 index 0000000..75c0354 --- /dev/null +++ b/boost/atomic/detail/wait_ops_emulated.hpp @@ -0,0 +1,97 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_emulated.hpp + * + * This header contains emulated (lock-based) implementation of the waiting and notifying atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_EMULATED_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_EMULATED_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Emulated implementation of waiting and notifying operations +template< typename Base > +struct wait_operations_emulated : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef lock_pool::scoped_lock< base_type::storage_alignment, true > scoped_lock; + typedef lock_pool::scoped_wait_state< base_type::storage_alignment > scoped_wait_state; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return false; + } + + static +#if defined(BOOST_MSVC) && BOOST_MSVC < 1500 + // In some cases, when this function is inlined, MSVC-8 (VS2005) x64 generates broken code that returns a bogus value from this function. + BOOST_NOINLINE +#endif + storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + storage_type const& s = const_cast< storage_type const& >(storage); + scoped_wait_state wait_state(&storage); + storage_type new_val = s; + while (new_val == old_val) + { + wait_state.wait(); + new_val = s; + } + + return new_val; + } + + static void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + scoped_lock lock(&storage); + lock_pool::notify_one(lock.get_lock_state(), &storage); + } + + static void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); + scoped_lock lock(&storage); + lock_pool::notify_all(lock.get_lock_state(), &storage); + } +}; + +template< typename Base, std::size_t Size, bool Interprocess > +struct wait_operations< Base, Size, false, Interprocess > : + public wait_operations_emulated< Base > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_EMULATED_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_freebsd_umtx.hpp b/boost/atomic/detail/wait_ops_freebsd_umtx.hpp new file mode 100644 index 0000000..28ef47e --- /dev/null +++ b/boost/atomic/detail/wait_ops_freebsd_umtx.hpp @@ -0,0 +1,119 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_freebsd_umtx.hpp + * + * This header contains implementation of the waiting/notifying atomic operations based on FreeBSD _umtx_op syscall. + * https://www.freebsd.org/cgi/man.cgi?query=_umtx_op&apropos=0&sektion=2&manpath=FreeBSD+11-current&format=html + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_FREEBSD_UMTX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_FREEBSD_UMTX_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(UMTX_OP_WAIT_UINT) || defined(UMTX_OP_WAIT) + +template< typename Base > +struct wait_operations_freebsd_umtx_common : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + ::_umtx_op(const_cast< storage_type* >(&storage), UMTX_OP_WAKE, 1u, NULL, NULL); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + ::_umtx_op(const_cast< storage_type* >(&storage), UMTX_OP_WAKE, (~static_cast< unsigned int >(0u)) >> 1, NULL, NULL); + } +}; + +#endif // defined(UMTX_OP_WAIT_UINT) || defined(UMTX_OP_WAIT) + +// UMTX_OP_WAIT_UINT only appeared in FreeBSD 8.0 +#if defined(UMTX_OP_WAIT_UINT) && BOOST_ATOMIC_DETAIL_SIZEOF_INT < BOOST_ATOMIC_DETAIL_SIZEOF_LONG + +template< typename Base, bool Interprocess > +struct wait_operations< Base, sizeof(unsigned int), true, Interprocess > : + public wait_operations_freebsd_umtx_common< Base > +{ + typedef wait_operations_freebsd_umtx_common< Base > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + ::_umtx_op(const_cast< storage_type* >(&storage), UMTX_OP_WAIT_UINT, old_val, NULL, NULL); + new_val = base_type::load(storage, order); + } + + return new_val; + } +}; + +#endif // defined(UMTX_OP_WAIT_UINT) && BOOST_ATOMIC_DETAIL_SIZEOF_INT < BOOST_ATOMIC_DETAIL_SIZEOF_LONG + +#if defined(UMTX_OP_WAIT) + +template< typename Base, bool Interprocess > +struct wait_operations< Base, sizeof(unsigned long), true, Interprocess > : + public wait_operations_freebsd_umtx_common< Base > +{ + typedef wait_operations_freebsd_umtx_common< Base > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + ::_umtx_op(const_cast< storage_type* >(&storage), UMTX_OP_WAIT, old_val, NULL, NULL); + new_val = base_type::load(storage, order); + } + + return new_val; + } +}; + +#endif // defined(UMTX_OP_WAIT) + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_FREEBSD_UMTX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_futex.hpp b/boost/atomic/detail/wait_ops_futex.hpp new file mode 100644 index 0000000..ec308a2 --- /dev/null +++ b/boost/atomic/detail/wait_ops_futex.hpp @@ -0,0 +1,111 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_futex.hpp + * + * This header contains implementation of the waiting/notifying atomic operations based on futexes. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_FUTEX_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_FUTEX_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename Base > +struct wait_operations< Base, 4u, true, false > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + atomics::detail::futex_wait_private(const_cast< storage_type* >(&storage), old_val); + new_val = base_type::load(storage, order); + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + atomics::detail::futex_signal_private(const_cast< storage_type* >(&storage)); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + atomics::detail::futex_broadcast_private(const_cast< storage_type* >(&storage)); + } +}; + +template< typename Base > +struct wait_operations< Base, 4u, true, true > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + atomics::detail::futex_wait(const_cast< storage_type* >(&storage), old_val); + new_val = base_type::load(storage, order); + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + atomics::detail::futex_signal(const_cast< storage_type* >(&storage)); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + atomics::detail::futex_broadcast(const_cast< storage_type* >(&storage)); + } +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_FUTEX_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_generic.hpp b/boost/atomic/detail/wait_ops_generic.hpp new file mode 100644 index 0000000..8462a44 --- /dev/null +++ b/boost/atomic/detail/wait_ops_generic.hpp @@ -0,0 +1,143 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_generic.hpp + * + * This header contains generic (lock-based) implementation of the waiting/notifying atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +//! Generic implementation of waiting/notifying operations +template< typename Base, bool Interprocess > +struct wait_operations_generic; + +template< typename Base > +struct wait_operations_generic< Base, false > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + typedef lock_pool::scoped_lock< base_type::storage_alignment, true > scoped_lock; + typedef lock_pool::scoped_wait_state< base_type::storage_alignment > scoped_wait_state; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return false; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + if (new_val == old_val) + { + scoped_wait_state wait_state(&storage); + new_val = base_type::load(storage, order); + while (new_val == old_val) + { + wait_state.wait(); + new_val = base_type::load(storage, order); + } + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + scoped_lock lock(&storage); + lock_pool::notify_one(lock.get_lock_state(), &storage); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + scoped_lock lock(&storage); + lock_pool::notify_all(lock.get_lock_state(), &storage); + } +}; + +template< typename Base > +struct wait_operations_generic< Base, true > : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return false; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + if (new_val == old_val) + { + for (unsigned int i = 0u; i < 16u; ++i) + { + atomics::detail::pause(); + new_val = base_type::load(storage, order); + if (new_val != old_val) + goto finish; + } + + do + { + atomics::detail::wait_some(); + new_val = base_type::load(storage, order); + } + while (new_val == old_val); + } + + finish: + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile&) BOOST_NOEXCEPT + { + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile&) BOOST_NOEXCEPT + { + } +}; + +template< typename Base, std::size_t Size, bool Interprocess > +struct wait_operations< Base, Size, true, Interprocess > : + public wait_operations_generic< Base, Interprocess > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_GENERIC_HPP_INCLUDED_ diff --git a/boost/atomic/detail/wait_ops_windows.hpp b/boost/atomic/detail/wait_ops_windows.hpp new file mode 100644 index 0000000..5e77b53 --- /dev/null +++ b/boost/atomic/detail/wait_ops_windows.hpp @@ -0,0 +1,179 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2020 Andrey Semashev + */ +/*! + * \file atomic/detail/wait_ops_windows.hpp + * + * This header contains implementation of the waiting/notifying atomic operations on Windows. + */ + +#ifndef BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#if defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) +#include +#if (defined(BOOST_ATOMIC_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_ATOMIC_NO_LIB))) && !defined(BOOST_ATOMIC_NO_SYNCHRONIZATION_LIB) +#define BOOST_LIB_NAME "synchronization" +#if defined(BOOST_AUTO_LINK_NOMANGLE) +#include +#else // defined(BOOST_AUTO_LINK_NOMANGLE) +#define BOOST_AUTO_LINK_NOMANGLE +#include +#undef BOOST_AUTO_LINK_NOMANGLE +#endif // defined(BOOST_AUTO_LINK_NOMANGLE) +#endif // (defined(BOOST_ATOMIC_FORCE_AUTO_LINK) || (!defined(BOOST_ALL_NO_LIB) && !defined(BOOST_ATOMIC_NO_LIB))) && !defined(BOOST_ATOMIC_NO_SYNCHRONIZATION_LIB) +#else // defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) +#include +#include +#include +#endif // defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) + +template< typename Base, std::size_t Size > +struct wait_operations_windows : + public Base +{ + typedef Base base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = true; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + return true; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + boost::winapi::WaitOnAddress(const_cast< storage_type* >(&storage), &old_val, Size, boost::winapi::infinite); + new_val = base_type::load(storage, order); + } + + return new_val; + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + boost::winapi::WakeByAddressSingle(const_cast< storage_type* >(&storage)); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + boost::winapi::WakeByAddressAll(const_cast< storage_type* >(&storage)); + } +}; + +#else // defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) + +template< typename Base, std::size_t Size > +struct wait_operations_windows : + public atomics::detail::wait_operations_generic< Base, false > +{ + typedef atomics::detail::wait_operations_generic< Base, false > base_type; + typedef typename base_type::storage_type storage_type; + + static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = false; + + static BOOST_FORCEINLINE bool has_native_wait_notify(storage_type const volatile&) BOOST_NOEXCEPT + { + ensure_wait_functions_initialized(); + return atomics::detail::wait_on_address != NULL; + } + + static BOOST_FORCEINLINE storage_type wait(storage_type const volatile& storage, storage_type old_val, memory_order order) BOOST_NOEXCEPT + { + ensure_wait_functions_initialized(); + + if (BOOST_LIKELY(atomics::detail::wait_on_address != NULL)) + { + storage_type new_val = base_type::load(storage, order); + while (new_val == old_val) + { + atomics::detail::wait_on_address(const_cast< storage_type* >(&storage), &old_val, Size, boost::winapi::infinite); + new_val = base_type::load(storage, order); + } + + return new_val; + } + else + { + return base_type::wait(storage, old_val, order); + } + } + + static BOOST_FORCEINLINE void notify_one(storage_type volatile& storage) BOOST_NOEXCEPT + { + ensure_wait_functions_initialized(); + + if (BOOST_LIKELY(atomics::detail::wake_by_address_single != NULL)) + atomics::detail::wake_by_address_single(const_cast< storage_type* >(&storage)); + else + base_type::notify_one(storage); + } + + static BOOST_FORCEINLINE void notify_all(storage_type volatile& storage) BOOST_NOEXCEPT + { + ensure_wait_functions_initialized(); + + if (BOOST_LIKELY(atomics::detail::wake_by_address_all != NULL)) + atomics::detail::wake_by_address_all(const_cast< storage_type* >(&storage)); + else + base_type::notify_all(storage); + } +}; + +#endif // defined(BOOST_ATOMIC_DETAIL_WINDOWS_HAS_WAIT_ON_ADDRESS) + +template< typename Base > +struct wait_operations< Base, 1u, true, false > : + public wait_operations_windows< Base, 1u > +{ +}; + +template< typename Base > +struct wait_operations< Base, 2u, true, false > : + public wait_operations_windows< Base, 2u > +{ +}; + +template< typename Base > +struct wait_operations< Base, 4u, true, false > : + public wait_operations_windows< Base, 4u > +{ +}; + +template< typename Base > +struct wait_operations< Base, 8u, true, false > : + public wait_operations_windows< Base, 8u > +{ +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#include + +#endif // BOOST_ATOMIC_DETAIL_WAIT_OPS_WINDOWS_HPP_INCLUDED_ diff --git a/boost/bind.hpp b/boost/bind.hpp deleted file mode 100644 index 48cc409..0000000 --- a/boost/bind.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef BOOST_BIND_HPP_INCLUDED -#define BOOST_BIND_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// bind.hpp - binds function objects to arguments -// -// Copyright (c) 2009, 2015 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// -// For backward compatibility, this header includes -// and then imports the placeholders _1, _2, -// _3, ... into the global namespace. Definitions in the global -// namespace are not a good practice and this use is deprecated. -// Please switch to including directly, -// adding the using directive locally where appropriate. -// Alternatively, the existing behavior may be preserved by defining -// the macro BOOST_BIND_GLOBAL_PLACEHOLDERS. - -#include -#include - -#ifndef BOOST_BIND_NO_PLACEHOLDERS - -#if !defined(BOOST_BIND_GLOBAL_PLACEHOLDERS) - -BOOST_PRAGMA_MESSAGE( - "The practice of declaring the Bind placeholders (_1, _2, ...) " - "in the global namespace is deprecated. Please use " - " + using namespace boost::placeholders, " - "or define BOOST_BIND_GLOBAL_PLACEHOLDERS to retain the current behavior." -) - -#endif - -#if defined(BOOST_CLANG) -# pragma clang diagnostic push -# if __has_warning("-Wheader-hygiene") -# pragma clang diagnostic ignored "-Wheader-hygiene" -# endif -#endif - -using namespace boost::placeholders; - -#if defined(BOOST_CLANG) -# pragma clang diagnostic pop -#endif - -#endif // #ifndef BOOST_BIND_NO_PLACEHOLDERS - -#endif // #ifndef BOOST_BIND_HPP_INCLUDED diff --git a/boost/bind/bind.hpp b/boost/bind/bind.hpp deleted file mode 100644 index fd0ee14..0000000 --- a/boost/bind/bind.hpp +++ /dev/null @@ -1,2346 +0,0 @@ -#ifndef BOOST_BIND_BIND_HPP_INCLUDED -#define BOOST_BIND_BIND_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// bind.hpp - binds function objects to arguments -// -// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd. -// Copyright (c) 2001 David Abrahams -// Copyright (c) 2005 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) -#include // std::forward -#endif - -// Borland-specific bug, visit_each() silently fails to produce code - -#if defined(BOOST_BORLANDC) -# define BOOST_BIND_VISIT_EACH boost::visit_each -#else -# define BOOST_BIND_VISIT_EACH visit_each -#endif - -#include - -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4512) // assignment operator could not be generated -#endif - -namespace boost -{ - -template class weak_ptr; - -namespace _bi // implementation details -{ - -// ref_compare - -template bool ref_compare( T const & a, T const & b, long ) -{ - return a == b; -} - -template bool ref_compare( arg const &, arg const &, int ) -{ - return true; -} - -template bool ref_compare( arg (*) (), arg (*) (), int ) -{ - return true; -} - -template bool ref_compare( reference_wrapper const & a, reference_wrapper const & b, int ) -{ - return a.get_pointer() == b.get_pointer(); -} - -// bind_t forward declaration for listN - -template class bind_t; - -template bool ref_compare( bind_t const & a, bind_t const & b, int ) -{ - return a.compare( b ); -} - -// value - -template class value -{ -public: - - value(T const & t): t_(t) {} - - T & get() { return t_; } - T const & get() const { return t_; } - - bool operator==(value const & rhs) const - { - return t_ == rhs.t_; - } - -private: - - T t_; -}; - -// ref_compare for weak_ptr - -template bool ref_compare( value< weak_ptr > const & a, value< weak_ptr > const & b, int ) -{ - return !(a.get() < b.get()) && !(b.get() < a.get()); -} - -// type - -template class type {}; - -// unwrap - -template struct unwrapper -{ - static inline F & unwrap( F & f, long ) - { - return f; - } - - template static inline F2 & unwrap( reference_wrapper rf, int ) - { - return rf.get(); - } - - template static inline _mfi::dm unwrap( R T::* pm, int ) - { - return _mfi::dm( pm ); - } -}; - -// listN - -class list0 -{ -public: - - list0() {} - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A &, long) - { - return unwrapper::unwrap(f, 0)(); - } - - template R operator()(type, F const & f, A &, long) const - { - return unwrapper::unwrap(f, 0)(); - } - - template void operator()(type, F & f, A &, int) - { - unwrapper::unwrap(f, 0)(); - } - - template void operator()(type, F const & f, A &, int) const - { - unwrapper::unwrap(f, 0)(); - } - - template void accept(V &) const - { - } - - bool operator==(list0 const &) const - { - return true; - } -}; - -#ifdef BOOST_MSVC -// MSVC is bright enough to realise that the parameter rhs -// in operator==may be unused for some template argument types: -#pragma warning(push) -#pragma warning(disable:4100) -#endif - -template< class A1 > class list1: private storage1< A1 > -{ -private: - - typedef storage1< A1 > base_type; - -public: - - explicit list1( A1 a1 ): base_type( a1 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list1 const & rhs) const - { - return ref_compare(base_type::a1_, rhs.a1_, 0); - } -}; - -struct logical_and; -struct logical_or; - -template< class A1, class A2 > class list2: private storage2< A1, A2 > -{ -private: - - typedef storage2< A1, A2 > base_type; - -public: - - list2( A1 a1, A2 a2 ): base_type( a1, a2 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]); - } - - template bool operator()( type, logical_and & /*f*/, A & a, int ) - { - return a[ base_type::a1_ ] && a[ base_type::a2_ ]; - } - - template bool operator()( type, logical_and const & /*f*/, A & a, int ) const - { - return a[ base_type::a1_ ] && a[ base_type::a2_ ]; - } - - template bool operator()( type, logical_or & /*f*/, A & a, int ) - { - return a[ base_type::a1_ ] || a[ base_type::a2_ ]; - } - - template bool operator()( type, logical_or const & /*f*/, A & a, int ) const - { - return a[ base_type::a1_ ] || a[ base_type::a2_ ]; - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list2 const & rhs) const - { - return ref_compare(base_type::a1_, rhs.a1_, 0) && ref_compare(base_type::a2_, rhs.a2_, 0); - } -}; - -template< class A1, class A2, class A3 > class list3: private storage3< A1, A2, A3 > -{ -private: - - typedef storage3< A1, A2, A3 > base_type; - -public: - - list3( A1 a1, A2 a2, A3 a3 ): base_type( a1, a2, a3 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list3 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ); - } -}; - -template< class A1, class A2, class A3, class A4 > class list4: private storage4< A1, A2, A3, A4 > -{ -private: - - typedef storage4< A1, A2, A3, A4 > base_type; - -public: - - list4( A1 a1, A2 a2, A3 a3, A4 a4 ): base_type( a1, a2, a3, a4 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list4 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5 > class list5: private storage5< A1, A2, A3, A4, A5 > -{ -private: - - typedef storage5< A1, A2, A3, A4, A5 > base_type; - -public: - - list5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): base_type( a1, a2, a3, a4, a5 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - A5 operator[] (boost::arg<5>) const { return base_type::a5_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list5 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ) && - ref_compare( base_type::a5_, rhs.a5_, 0 ); - } -}; - -template class list6: private storage6< A1, A2, A3, A4, A5, A6 > -{ -private: - - typedef storage6< A1, A2, A3, A4, A5, A6 > base_type; - -public: - - list6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): base_type( a1, a2, a3, a4, a5, a6 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - A5 operator[] (boost::arg<5>) const { return base_type::a5_; } - A6 operator[] (boost::arg<6>) const { return base_type::a6_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } - A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list6 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ) && - ref_compare( base_type::a5_, rhs.a5_, 0 ) && - ref_compare( base_type::a6_, rhs.a6_, 0 ); - } -}; - -template class list7: private storage7< A1, A2, A3, A4, A5, A6, A7 > -{ -private: - - typedef storage7< A1, A2, A3, A4, A5, A6, A7 > base_type; - -public: - - list7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): base_type( a1, a2, a3, a4, a5, a6, a7 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - A5 operator[] (boost::arg<5>) const { return base_type::a5_; } - A6 operator[] (boost::arg<6>) const { return base_type::a6_; } - A7 operator[] (boost::arg<7>) const { return base_type::a7_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } - A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } - A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list7 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ) && - ref_compare( base_type::a5_, rhs.a5_, 0 ) && - ref_compare( base_type::a6_, rhs.a6_, 0 ) && - ref_compare( base_type::a7_, rhs.a7_, 0 ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > class list8: private storage8< A1, A2, A3, A4, A5, A6, A7, A8 > -{ -private: - - typedef storage8< A1, A2, A3, A4, A5, A6, A7, A8 > base_type; - -public: - - list8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - A5 operator[] (boost::arg<5>) const { return base_type::a5_; } - A6 operator[] (boost::arg<6>) const { return base_type::a6_; } - A7 operator[] (boost::arg<7>) const { return base_type::a7_; } - A8 operator[] (boost::arg<8>) const { return base_type::a8_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } - A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } - A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } - A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list8 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ) && - ref_compare( base_type::a5_, rhs.a5_, 0 ) && - ref_compare( base_type::a6_, rhs.a6_, 0 ) && - ref_compare( base_type::a7_, rhs.a7_, 0 ) && - ref_compare( base_type::a8_, rhs.a8_, 0 ); - } -}; - -template class list9: private storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > -{ -private: - - typedef storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > base_type; - -public: - - list9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8, a9 ) {} - - A1 operator[] (boost::arg<1>) const { return base_type::a1_; } - A2 operator[] (boost::arg<2>) const { return base_type::a2_; } - A3 operator[] (boost::arg<3>) const { return base_type::a3_; } - A4 operator[] (boost::arg<4>) const { return base_type::a4_; } - A5 operator[] (boost::arg<5>) const { return base_type::a5_; } - A6 operator[] (boost::arg<6>) const { return base_type::a6_; } - A7 operator[] (boost::arg<7>) const { return base_type::a7_; } - A8 operator[] (boost::arg<8>) const { return base_type::a8_; } - A9 operator[] (boost::arg<9>) const { return base_type::a9_; } - - A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; } - A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; } - A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; } - A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; } - A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; } - A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; } - A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; } - A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; } - A9 operator[] (boost::arg<9> (*) ()) const { return base_type::a9_; } - - template T & operator[] (_bi::value & v) const { return v.get(); } - - template T const & operator[] (_bi::value const & v) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const { return b.eval(*this); } - - template typename result_traits::type operator[] (bind_t const & b) const { return b.eval(*this); } - - template R operator()(type, F & f, A & a, long) - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); - } - - template R operator()(type, F const & f, A & a, long) const - { - return unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); - } - - template void operator()(type, F & f, A & a, int) - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); - } - - template void operator()(type, F const & f, A & a, int) const - { - unwrapper::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]); - } - - template void accept(V & v) const - { - base_type::accept(v); - } - - bool operator==(list9 const & rhs) const - { - return - - ref_compare( base_type::a1_, rhs.a1_, 0 ) && - ref_compare( base_type::a2_, rhs.a2_, 0 ) && - ref_compare( base_type::a3_, rhs.a3_, 0 ) && - ref_compare( base_type::a4_, rhs.a4_, 0 ) && - ref_compare( base_type::a5_, rhs.a5_, 0 ) && - ref_compare( base_type::a6_, rhs.a6_, 0 ) && - ref_compare( base_type::a7_, rhs.a7_, 0 ) && - ref_compare( base_type::a8_, rhs.a8_, 0 ) && - ref_compare( base_type::a9_, rhs.a9_, 0 ); - } -}; - -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif - -// bind_t - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && BOOST_GCC < 40600) - -template< class A1 > class rrlist1 -{ -private: - - A1 & a1_; // not A1&& because of msvc-10.0 - -public: - - explicit rrlist1( A1 & a1 ): a1_( a1 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } // not static_cast because of g++ 4.9 - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist1 a( a1_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist1 a( a1_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2 > class rrlist2 -{ -private: - - A1 & a1_; - A2 & a2_; - -public: - - rrlist2( A1 & a1, A2 & a2 ): a1_( a1 ), a2_( a2 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist2 a( a1_, a2_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist2 a( a1_, a2_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3 > class rrlist3 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - -public: - - rrlist3( A1 & a1, A2 & a2, A3 & a3 ): a1_( a1 ), a2_( a2 ), a3_( a3 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist3 a( a1_, a2_, a3_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist3 a( a1_, a2_, a3_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4 > class rrlist4 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - -public: - - rrlist4( A1 & a1, A2 & a2, A3 & a3, A4 & a4 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist4 a( a1_, a2_, a3_, a4_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist4 a( a1_, a2_, a3_, a4_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5 > class rrlist5 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - A5 & a5_; - -public: - - rrlist5( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5>) const { return std::forward( a5_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward( a5_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist5 a( a1_, a2_, a3_, a4_, a5_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist5 a( a1_, a2_, a3_, a4_, a5_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5, class A6 > class rrlist6 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - A5 & a5_; - A6 & a6_; - -public: - - rrlist6( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5>) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6>) const { return std::forward( a6_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward( a6_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist6 a( a1_, a2_, a3_, a4_, a5_, a6_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist6 a( a1_, a2_, a3_, a4_, a5_, a6_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5, class A6, class A7 > class rrlist7 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - A5 & a5_; - A6 & a6_; - A7 & a7_; - -public: - - rrlist7( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5>) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6>) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7>) const { return std::forward( a7_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward( a7_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist7 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist7 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > class rrlist8 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - A5 & a5_; - A6 & a6_; - A7 & a7_; - A8 & a8_; - -public: - - rrlist8( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ), a8_( a8 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5>) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6>) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7>) const { return std::forward( a7_ ); } - A8 && operator[] (boost::arg<8>) const { return std::forward( a8_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward( a7_ ); } - A8 && operator[] (boost::arg<8> (*) ()) const { return std::forward( a8_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist8 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist8 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_ ); - return b.eval( a ); - } -}; - -template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > class rrlist9 -{ -private: - - A1 & a1_; - A2 & a2_; - A3 & a3_; - A4 & a4_; - A5 & a5_; - A6 & a6_; - A7 & a7_; - A8 & a8_; - A9 & a9_; - -public: - - rrlist9( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ), a8_( a8 ), a9_( a9 ) {} - - A1 && operator[] (boost::arg<1>) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2>) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3>) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4>) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5>) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6>) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7>) const { return std::forward( a7_ ); } - A8 && operator[] (boost::arg<8>) const { return std::forward( a8_ ); } - A9 && operator[] (boost::arg<9>) const { return std::forward( a9_ ); } - - A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward( a1_ ); } - A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward( a2_ ); } - A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward( a3_ ); } - A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward( a4_ ); } - A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward( a5_ ); } - A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward( a6_ ); } - A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward( a7_ ); } - A8 && operator[] (boost::arg<8> (*) ()) const { return std::forward( a8_ ); } - A9 && operator[] (boost::arg<9> (*) ()) const { return std::forward( a9_ ); } - - template T & operator[] ( _bi::value & v ) const { return v.get(); } - - template T const & operator[] ( _bi::value const & v ) const { return v.get(); } - - template T & operator[] (reference_wrapper const & v) const { return v.get(); } - - template typename result_traits::type operator[] (bind_t & b) const - { - rrlist9 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_ ); - return b.eval( a ); - } - - template typename result_traits::type operator[] (bind_t const & b) const - { - rrlist9 a( a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_ ); - return b.eval( a ); - } -}; - -template class bind_t -{ -private: - - F f_; - L l_; - -public: - - typedef typename result_traits::type result_type; - typedef bind_t this_type; - - bind_t( F f, L const & l ): f_( f ), l_( l ) {} - - // - - result_type operator()() - { - list0 a; - return l_( type(), f_, a, 0 ); - } - - result_type operator()() const - { - list0 a; - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1 ) - { - rrlist1< A1 > a( a1 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1 ) const - { - rrlist1< A1 > a( a1 ); - return l_(type(), f_, a, 0); - } - - template result_type operator()( A1 && a1, A2 && a2 ) - { - rrlist2< A1, A2 > a( a1, a2 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2 ) const - { - rrlist2< A1, A2 > a( a1, a2 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3 ) - { - rrlist3< A1, A2, A3 > a( a1, a2, a3 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3 ) const - { - rrlist3< A1, A2, A3 > a( a1, a2, a3 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) - { - rrlist4< A1, A2, A3, A4 > a( a1, a2, a3, a4 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) const - { - rrlist4< A1, A2, A3, A4 > a( a1, a2, a3, a4 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) - { - rrlist5< A1, A2, A3, A4, A5 > a( a1, a2, a3, a4, a5 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) const - { - rrlist5< A1, A2, A3, A4, A5 > a( a1, a2, a3, a4, a5 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) - { - rrlist6< A1, A2, A3, A4, A5, A6 > a( a1, a2, a3, a4, a5, a6 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) const - { - rrlist6< A1, A2, A3, A4, A5, A6 > a( a1, a2, a3, a4, a5, a6 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) - { - rrlist7< A1, A2, A3, A4, A5, A6, A7 > a( a1, a2, a3, a4, a5, a6, a7 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) const - { - rrlist7< A1, A2, A3, A4, A5, A6, A7 > a( a1, a2, a3, a4, a5, a6, a7 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) - { - rrlist8< A1, A2, A3, A4, A5, A6, A7, A8 > a( a1, a2, a3, a4, a5, a6, a7, a8 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) const - { - rrlist8< A1, A2, A3, A4, A5, A6, A7, A8 > a( a1, a2, a3, a4, a5, a6, a7, a8 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) - { - rrlist9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > a( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - return l_( type(), f_, a, 0 ); - } - - template result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) const - { - rrlist9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > a( a1, a2, a3, a4, a5, a6, a7, a8, a9 ); - return l_( type(), f_, a, 0 ); - } - - // - - template result_type eval( A & a ) - { - return l_( type(), f_, a, 0 ); - } - - template result_type eval( A & a ) const - { - return l_( type(), f_, a, 0 ); - } - - template void accept( V & v ) const - { -#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( BOOST_BORLANDC ) - using boost::visit_each; -#endif - - BOOST_BIND_VISIT_EACH( v, f_, 0 ); - l_.accept( v ); - } - - bool compare( this_type const & rhs ) const - { - return ref_compare( f_, rhs.f_, 0 ) && l_ == rhs.l_; - } -}; - -#elif !defined( BOOST_NO_VOID_RETURNS ) - -template class bind_t -{ -public: - - typedef bind_t this_type; - - bind_t(F f, L const & l): f_(f), l_(l) {} - -#define BOOST_BIND_RETURN return -#include -#undef BOOST_BIND_RETURN - -}; - -#else // no void returns - -template struct bind_t_generator -{ - -template class implementation -{ -public: - - typedef implementation this_type; - - implementation(F f, L const & l): f_(f), l_(l) {} - -#define BOOST_BIND_RETURN return -#include -#undef BOOST_BIND_RETURN - -}; - -}; - -template<> struct bind_t_generator -{ - -template class implementation -{ -private: - - typedef void R; - -public: - - typedef implementation this_type; - - implementation(F f, L const & l): f_(f), l_(l) {} - -#define BOOST_BIND_RETURN -#include -#undef BOOST_BIND_RETURN - -}; - -}; - -template class bind_t: public bind_t_generator::BOOST_NESTED_TEMPLATE implementation -{ -public: - - bind_t(F f, L const & l): bind_t_generator::BOOST_NESTED_TEMPLATE implementation(f, l) {} - -}; - -#endif - -// function_equal - -#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP - -// put overloads in _bi, rely on ADL - -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -template bool function_equal( bind_t const & a, bind_t const & b ) -{ - return a.compare(b); -} - -# else - -template bool function_equal_impl( bind_t const & a, bind_t const & b, int ) -{ - return a.compare(b); -} - -# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -#else // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP - -// put overloads in boost - -} // namespace _bi - -# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -template bool function_equal( _bi::bind_t const & a, _bi::bind_t const & b ) -{ - return a.compare(b); -} - -# else - -template bool function_equal_impl( _bi::bind_t const & a, _bi::bind_t const & b, int ) -{ - return a.compare(b); -} - -# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -namespace _bi -{ - -#endif // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP - -// add_value - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || (__SUNPRO_CC >= 0x530) - -#if defined( BOOST_BORLANDC ) && BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT(0x582) ) - -template struct add_value -{ - typedef _bi::value type; -}; - -#else - -template< class T, int I > struct add_value_2 -{ - typedef boost::arg type; -}; - -template< class T > struct add_value_2< T, 0 > -{ - typedef _bi::value< T > type; -}; - -template struct add_value -{ - typedef typename add_value_2< T, boost::is_placeholder< T >::value >::type type; -}; - -#endif - -template struct add_value< value > -{ - typedef _bi::value type; -}; - -template struct add_value< reference_wrapper > -{ - typedef reference_wrapper type; -}; - -template struct add_value< arg > -{ - typedef boost::arg type; -}; - -template struct add_value< arg (*) () > -{ - typedef boost::arg (*type) (); -}; - -template struct add_value< bind_t > -{ - typedef bind_t type; -}; - -#else - -template struct _avt_0; - -template<> struct _avt_0<1> -{ - template struct inner - { - typedef T type; - }; -}; - -template<> struct _avt_0<2> -{ - template struct inner - { - typedef value type; - }; -}; - -typedef char (&_avt_r1) [1]; -typedef char (&_avt_r2) [2]; - -template _avt_r1 _avt_f(value); -template _avt_r1 _avt_f(reference_wrapper); -template _avt_r1 _avt_f(arg); -template _avt_r1 _avt_f(arg (*) ()); -template _avt_r1 _avt_f(bind_t); - -_avt_r2 _avt_f(...); - -template struct add_value -{ - static T t(); - typedef typename _avt_0::template inner::type type; -}; - -#endif - -// list_av_N - -template struct list_av_1 -{ - typedef typename add_value::type B1; - typedef list1 type; -}; - -template struct list_av_2 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef list2 type; -}; - -template struct list_av_3 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef list3 type; -}; - -template struct list_av_4 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef list4 type; -}; - -template struct list_av_5 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef typename add_value::type B5; - typedef list5 type; -}; - -template struct list_av_6 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef typename add_value::type B5; - typedef typename add_value::type B6; - typedef list6 type; -}; - -template struct list_av_7 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef typename add_value::type B5; - typedef typename add_value::type B6; - typedef typename add_value::type B7; - typedef list7 type; -}; - -template struct list_av_8 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef typename add_value::type B5; - typedef typename add_value::type B6; - typedef typename add_value::type B7; - typedef typename add_value::type B8; - typedef list8 type; -}; - -template struct list_av_9 -{ - typedef typename add_value::type B1; - typedef typename add_value::type B2; - typedef typename add_value::type B3; - typedef typename add_value::type B4; - typedef typename add_value::type B5; - typedef typename add_value::type B6; - typedef typename add_value::type B7; - typedef typename add_value::type B8; - typedef typename add_value::type B9; - typedef list9 type; -}; - -// operator! - -struct logical_not -{ - template bool operator()(V const & v) const { return !v; } -}; - -template - bind_t< bool, logical_not, list1< bind_t > > - operator! (bind_t const & f) -{ - typedef list1< bind_t > list_type; - return bind_t ( logical_not(), list_type(f) ); -} - -// relational operators - -#define BOOST_BIND_OPERATOR( op, name ) \ -\ -struct name \ -{ \ - template bool operator()(V const & v, W const & w) const { return v op w; } \ -}; \ - \ -template \ - bind_t< bool, name, list2< bind_t, typename add_value::type > > \ - operator op (bind_t const & f, A2 a2) \ -{ \ - typedef typename add_value::type B2; \ - typedef list2< bind_t, B2> list_type; \ - return bind_t ( name(), list_type(f, a2) ); \ -} - -BOOST_BIND_OPERATOR( ==, equal ) -BOOST_BIND_OPERATOR( !=, not_equal ) - -BOOST_BIND_OPERATOR( <, less ) -BOOST_BIND_OPERATOR( <=, less_equal ) - -BOOST_BIND_OPERATOR( >, greater ) -BOOST_BIND_OPERATOR( >=, greater_equal ) - -BOOST_BIND_OPERATOR( &&, logical_and ) -BOOST_BIND_OPERATOR( ||, logical_or ) - -#undef BOOST_BIND_OPERATOR - -#if defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) - -// resolve ambiguity with rel_ops - -#define BOOST_BIND_OPERATOR( op, name ) \ -\ -template \ - bind_t< bool, name, list2< bind_t, bind_t > > \ - operator op (bind_t const & f, bind_t const & g) \ -{ \ - typedef list2< bind_t, bind_t > list_type; \ - return bind_t ( name(), list_type(f, g) ); \ -} - -BOOST_BIND_OPERATOR( !=, not_equal ) -BOOST_BIND_OPERATOR( <=, less_equal ) -BOOST_BIND_OPERATOR( >, greater ) -BOOST_BIND_OPERATOR( >=, greater_equal ) - -#endif - -// visit_each, ADL - -#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( BOOST_BORLANDC ) \ - && !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) - -template void visit_each( V & v, value const & t, int ) -{ - using boost::visit_each; - BOOST_BIND_VISIT_EACH( v, t.get(), 0 ); -} - -template void visit_each( V & v, bind_t const & t, int ) -{ - t.accept( v ); -} - -#endif - -} // namespace _bi - -// visit_each, no ADL - -#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) || defined( BOOST_BORLANDC ) \ - || (defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) - -template void visit_each( V & v, _bi::value const & t, int ) -{ - BOOST_BIND_VISIT_EACH( v, t.get(), 0 ); -} - -template void visit_each( V & v, _bi::bind_t const & t, int ) -{ - t.accept( v ); -} - -#endif - -// is_bind_expression - -template< class T > struct is_bind_expression -{ - enum _vt { value = 0 }; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template< class R, class F, class L > struct is_bind_expression< _bi::bind_t< R, F, L > > -{ - enum _vt { value = 1 }; -}; - -#endif - -// bind - -#ifndef BOOST_BIND -#define BOOST_BIND bind -#endif - -// generic function objects - -template - _bi::bind_t - BOOST_BIND(F f) -{ - typedef _bi::list0 list_type; - return _bi::bind_t (f, list_type()); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1) -{ - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t (f, list_type(a1)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2) -{ - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t (f, list_type(a1, a2)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3) -{ - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -// generic function objects, alternative syntax - -template - _bi::bind_t - BOOST_BIND(boost::type, F f) -{ - typedef _bi::list0 list_type; - return _bi::bind_t (f, list_type()); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1) -{ - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t (f, list_type(a1)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2) -{ - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t (f, list_type(a1, a2)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3) -{ - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t::type> - BOOST_BIND(boost::type, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) - -// adaptable function objects - -template - _bi::bind_t<_bi::unspecified, F, _bi::list0> - BOOST_BIND(F f) -{ - typedef _bi::list0 list_type; - return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type()); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_1::type> - BOOST_BIND(F f, A1 a1) -{ - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_2::type> - BOOST_BIND(F f, A1 a1, A2 a2) -{ - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1, a2)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_3::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3) -{ - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_4::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_5::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_6::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_7::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_8::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_9::type> - BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -#endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) - -// function pointers - -#define BOOST_BIND_CC -#define BOOST_BIND_ST -#define BOOST_BIND_NOEXCEPT - -#include - -# if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) -# undef BOOST_BIND_NOEXCEPT -# define BOOST_BIND_NOEXCEPT noexcept -# include -# endif - -#undef BOOST_BIND_CC -#undef BOOST_BIND_ST -#undef BOOST_BIND_NOEXCEPT - -#if defined(BOOST_BIND_ENABLE_STDCALL) && !defined(_M_X64) - -#define BOOST_BIND_CC __stdcall -#define BOOST_BIND_ST -#define BOOST_BIND_NOEXCEPT - -#include - -#undef BOOST_BIND_CC -#undef BOOST_BIND_ST -#undef BOOST_BIND_NOEXCEPT - -#endif - -#if defined(BOOST_BIND_ENABLE_FASTCALL) && !defined(_M_X64) - -#define BOOST_BIND_CC __fastcall -#define BOOST_BIND_ST -#define BOOST_BIND_NOEXCEPT - -#include - -#undef BOOST_BIND_CC -#undef BOOST_BIND_ST -#undef BOOST_BIND_NOEXCEPT - -#endif - -#ifdef BOOST_BIND_ENABLE_PASCAL - -#define BOOST_BIND_ST pascal -#define BOOST_BIND_CC -#define BOOST_BIND_NOEXCEPT - -#include - -#undef BOOST_BIND_ST -#undef BOOST_BIND_CC -#undef BOOST_BIND_NOEXCEPT - -#endif - -// member function pointers - -#define BOOST_BIND_MF_NAME(X) X -#define BOOST_BIND_MF_CC -#define BOOST_BIND_MF_NOEXCEPT - -#include -#include - -# if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) -# undef BOOST_BIND_MF_NOEXCEPT -# define BOOST_BIND_MF_NOEXCEPT noexcept -# include -# include -# endif - -#undef BOOST_BIND_MF_NAME -#undef BOOST_BIND_MF_CC -#undef BOOST_BIND_MF_NOEXCEPT - -#if defined(BOOST_MEM_FN_ENABLE_CDECL) && !defined(_M_X64) - -#define BOOST_BIND_MF_NAME(X) X##_cdecl -#define BOOST_BIND_MF_CC __cdecl -#define BOOST_BIND_MF_NOEXCEPT - -#include -#include - -#undef BOOST_BIND_MF_NAME -#undef BOOST_BIND_MF_CC -#undef BOOST_BIND_MF_NOEXCEPT - -#endif - -#if defined(BOOST_MEM_FN_ENABLE_STDCALL) && !defined(_M_X64) - -#define BOOST_BIND_MF_NAME(X) X##_stdcall -#define BOOST_BIND_MF_CC __stdcall -#define BOOST_BIND_MF_NOEXCEPT - -#include -#include - -#undef BOOST_BIND_MF_NAME -#undef BOOST_BIND_MF_CC -#undef BOOST_BIND_MF_NOEXCEPT - -#endif - -#if defined(BOOST_MEM_FN_ENABLE_FASTCALL) && !defined(_M_X64) - -#define BOOST_BIND_MF_NAME(X) X##_fastcall -#define BOOST_BIND_MF_CC __fastcall -#define BOOST_BIND_MF_NOEXCEPT - -#include -#include - -#undef BOOST_BIND_MF_NAME -#undef BOOST_BIND_MF_CC -#undef BOOST_BIND_MF_NOEXCEPT - -#endif - -// data member pointers - -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - || ( defined(BOOST_BORLANDC) && BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT( 0x620 ) ) ) - -template -_bi::bind_t< R, _mfi::dm, typename _bi::list_av_1::type > - BOOST_BIND(R T::*f, A1 a1) -{ - typedef _mfi::dm F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t( F(f), list_type(a1) ); -} - -#else - -namespace _bi -{ - -template< class Pm, int I > struct add_cref; - -template< class M, class T > struct add_cref< M T::*, 0 > -{ - typedef M type; -}; - -template< class M, class T > struct add_cref< M T::*, 1 > -{ -#ifdef BOOST_MSVC -#pragma warning(push) -#pragma warning(disable:4180) -#endif - typedef M const & type; -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif -}; - -template< class R, class T > struct add_cref< R (T::*) (), 1 > -{ - typedef void type; -}; - -#if !defined(__IBMCPP__) || __IBMCPP_FUNC_CV_TMPL_ARG_DEDUCTION - -template< class R, class T > struct add_cref< R (T::*) () const, 1 > -{ - typedef void type; -}; - -#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) - -template< class R, class T > struct add_cref< R (T::*) () const noexcept, 1 > -{ - typedef void type; -}; - -#endif // __cpp_noexcept_function_type - -#endif // __IBMCPP__ - -template struct isref -{ - enum value_type { value = 0 }; -}; - -template struct isref< R& > -{ - enum value_type { value = 1 }; -}; - -template struct isref< R* > -{ - enum value_type { value = 1 }; -}; - -template struct dm_result -{ - typedef typename add_cref< Pm, 1 >::type type; -}; - -template struct dm_result< Pm, bind_t > -{ - typedef typename bind_t::result_type result_type; - typedef typename add_cref< Pm, isref< result_type >::value >::type type; -}; - -} // namespace _bi - -template< class A1, class M, class T > - -_bi::bind_t< - typename _bi::dm_result< M T::*, A1 >::type, - _mfi::dm, - typename _bi::list_av_1::type -> - -BOOST_BIND( M T::*f, A1 a1 ) -{ - typedef typename _bi::dm_result< M T::*, A1 >::type result_type; - typedef _mfi::dm F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t< result_type, F, list_type >( F( f ), list_type( a1 ) ); -} - -#endif - -} // namespace boost - -#ifndef BOOST_BIND_NO_PLACEHOLDERS - -# include - -#endif - -#ifdef BOOST_MSVC -# pragma warning(default: 4512) // assignment operator could not be generated -# pragma warning(pop) -#endif - -#endif // #ifndef BOOST_BIND_BIND_HPP_INCLUDED diff --git a/boost/bind/bind_cc.hpp b/boost/bind/bind_cc.hpp deleted file mode 100644 index 278aa9a..0000000 --- a/boost/bind/bind_cc.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// bind/bind_cc.hpp - support for different calling conventions -// -// Do not include this header directly. -// -// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -template - _bi::bind_t - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) () BOOST_BIND_NOEXCEPT) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) () BOOST_BIND_NOEXCEPT; - typedef _bi::list0 list_type; - return _bi::bind_t (f, list_type()); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1) BOOST_BIND_NOEXCEPT, A1 a1) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t (f, list_type(a1)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t (f, list_type(a1, a2)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t::type> - BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8, B9) BOOST_BIND_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8, B9) BOOST_BIND_NOEXCEPT; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} diff --git a/boost/bind/bind_mf2_cc.hpp b/boost/bind/bind_mf2_cc.hpp deleted file mode 100644 index be20b1d..0000000 --- a/boost/bind/bind_mf2_cc.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// bind/bind_mf2_cc.hpp - member functions, type<> syntax -// -// Do not include this header directly. -// -// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. -// Copyright (c) 2008 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -// 0 - -template - _bi::bind_t, typename _bi::list_av_1::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) () BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -template - _bi::bind_t, typename _bi::list_av_1::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) () const BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -// 1 - -template - _bi::bind_t, typename _bi::list_av_2::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -template - _bi::bind_t, typename _bi::list_av_2::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -// 2 - -template - _bi::bind_t, typename _bi::list_av_3::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -template - _bi::bind_t, typename _bi::list_av_3::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -// 3 - -template - _bi::bind_t, typename _bi::list_av_4::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t, typename _bi::list_av_4::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -// 4 - -template - _bi::bind_t, typename _bi::list_av_5::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t, typename _bi::list_av_5::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -// 5 - -template - _bi::bind_t, typename _bi::list_av_6::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t, typename _bi::list_av_6::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -// 6 - -template - _bi::bind_t, typename _bi::list_av_7::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t, typename _bi::list_av_7::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -// 7 - -template - _bi::bind_t, typename _bi::list_av_8::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t, typename _bi::list_av_8::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -// 8 - -template - _bi::bind_t, typename _bi::list_av_9::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template - _bi::bind_t, typename _bi::list_av_9::type> - BOOST_BIND(boost::type, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} diff --git a/boost/bind/bind_mf_cc.hpp b/boost/bind/bind_mf_cc.hpp deleted file mode 100644 index 5a1610b..0000000 --- a/boost/bind/bind_mf_cc.hpp +++ /dev/null @@ -1,441 +0,0 @@ -// -// bind/bind_mf_cc.hpp - support for different calling conventions -// -// Do not include this header directly. -// -// Copyright (c) 2001 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -// 0 - -template - _bi::bind_t, typename _bi::list_av_1::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -template - _bi::bind_t, typename _bi::list_av_1::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_1::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_1::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const BOOST_BIND_MF_NOEXCEPT, A1 a1) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf0) F; - typedef typename _bi::list_av_1::type list_type; - return _bi::bind_t(F(f), list_type(a1)); -} - -// 1 - -template - _bi::bind_t, typename _bi::list_av_2::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -template - _bi::bind_t, typename _bi::list_av_2::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_2::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_2::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf1) F; - typedef typename _bi::list_av_2::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2)); -} - -// 2 - -template - _bi::bind_t, typename _bi::list_av_3::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -template - _bi::bind_t, typename _bi::list_av_3::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_3::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_3::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf2) F; - typedef typename _bi::list_av_3::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3)); -} - -// 3 - -template - _bi::bind_t, typename _bi::list_av_4::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -template - _bi::bind_t, typename _bi::list_av_4::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_4::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_4::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf3) F; - typedef typename _bi::list_av_4::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4)); -} - -// 4 - -template - _bi::bind_t, typename _bi::list_av_5::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -template - _bi::bind_t, typename _bi::list_av_5::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_5::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_5::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf4) F; - typedef typename _bi::list_av_5::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5)); -} - -// 5 - -template - _bi::bind_t, typename _bi::list_av_6::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -template - _bi::bind_t, typename _bi::list_av_6::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_6::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_6::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf5) F; - typedef typename _bi::list_av_6::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6)); -} - -// 6 - -template - _bi::bind_t, typename _bi::list_av_7::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - _bi::bind_t, typename _bi::list_av_7::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_7::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_7::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf6) F; - typedef typename _bi::list_av_7::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7)); -} - -// 7 - -template - _bi::bind_t, typename _bi::list_av_8::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - _bi::bind_t, typename _bi::list_av_8::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_8::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_8::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf7) F; - typedef typename _bi::list_av_8::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8)); -} - -// 8 - -template - _bi::bind_t, typename _bi::list_av_9::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template - _bi::bind_t, typename _bi::list_av_9::type> - BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_9::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(mf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template - typename boost::enable_if_c::value, - _bi::bind_t, typename _bi::list_av_9::type> - >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const BOOST_BIND_MF_NOEXCEPT, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) -{ - typedef _mfi::BOOST_BIND_MF_NAME(cmf8) F; - typedef typename _bi::list_av_9::type list_type; - return _bi::bind_t(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9)); -} diff --git a/boost/bind/bind_template.hpp b/boost/bind/bind_template.hpp deleted file mode 100644 index 212ced7..0000000 --- a/boost/bind/bind_template.hpp +++ /dev/null @@ -1,345 +0,0 @@ -// -// bind/bind_template.hpp -// -// Do not include this header directly. -// -// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - - typedef typename result_traits::type result_type; - - result_type operator()() - { - list0 a; - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - result_type operator()() const - { - list0 a; - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1) - { - list1 a(a1); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1) const - { - list1 a(a1); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1) - { - list1 a(a1); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1) const - { - list1 a(a1); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2) - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2) const - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 & a2) - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 & a2) const - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - - template result_type operator()(A1 & a1, A2 const & a2) - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 const & a2) const - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - - template result_type operator()(A1 const & a1, A2 const & a2) - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2) const - { - list2 a(a1, a2); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3) - { - list3 a(a1, a2, a3); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3) const - { - list3 a(a1, a2, a3); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3) - { - list3 a(a1, a2, a3); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3) const - { - list3 a(a1, a2, a3); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) - { - list4 a(a1, a2, a3, a4); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const - { - list4 a(a1, a2, a3, a4); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4) - { - list4 a(a1, a2, a3, a4); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4) const - { - list4 a(a1, a2, a3, a4); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) - { - list5 a(a1, a2, a3, a4, a5); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const - { - list5 a(a1, a2, a3, a4, a5); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5) - { - list5 a(a1, a2, a3, a4, a5); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5) const - { - list5 a(a1, a2, a3, a4, a5); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) - { - list6 a(a1, a2, a3, a4, a5, a6); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const - { - list6 a(a1, a2, a3, a4, a5, a6); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6) - { - list6 a(a1, a2, a3, a4, a5, a6); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6) const - { - list6 a(a1, a2, a3, a4, a5, a6); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) - { - list7 a(a1, a2, a3, a4, a5, a6, a7); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const - { - list7 a(a1, a2, a3, a4, a5, a6, a7); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7) - { - list7 a(a1, a2, a3, a4, a5, a6, a7); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7) const - { - list7 a(a1, a2, a3, a4, a5, a6, a7); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) - { - list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const - { - list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8) - { - list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8) const - { - list8 a(a1, a2, a3, a4, a5, a6, a7, a8); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) - { - list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const - { - list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \ - && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238) - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9) - { - list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9) const - { - list9 a(a1, a2, a3, a4, a5, a6, a7, a8, a9); - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - -#endif - - template result_type eval(A & a) - { - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template result_type eval(A & a) const - { - BOOST_BIND_RETURN l_(type(), f_, a, 0); - } - - template void accept(V & v) const - { -#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( BOOST_BORLANDC ) - - using boost::visit_each; - -#endif - BOOST_BIND_VISIT_EACH(v, f_, 0); - l_.accept(v); - } - - bool compare(this_type const & rhs) const - { - return ref_compare(f_, rhs.f_, 0) && l_ == rhs.l_; - } - -private: - - F f_; - L l_; diff --git a/boost/bind/detail/is_same.hpp b/boost/bind/detail/is_same.hpp deleted file mode 100644 index 995b39f..0000000 --- a/boost/bind/detail/is_same.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef BOOST_BIND_DETAIL_IS_SAME_HPP_INCLUDED -#define BOOST_BIND_DETAIL_IS_SAME_HPP_INCLUDED - -// is_same::value is true when T1 == T2 -// -// Copyright 2014 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt - -#include - -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -namespace boost -{ -namespace _bi -{ - -template< class T1, class T2 > struct is_same -{ - BOOST_STATIC_CONSTANT( bool, value = false ); -}; - -template< class T > struct is_same< T, T > -{ - BOOST_STATIC_CONSTANT( bool, value = true ); -}; - -} // namespace _bi -} // namespace boost - -#endif // #ifndef BOOST_BIND_DETAIL_IS_SAME_HPP_INCLUDED diff --git a/boost/bind/detail/requires_cxx11.hpp b/boost/bind/detail/requires_cxx11.hpp index e78d8f9..a104d06 100644 --- a/boost/bind/detail/requires_cxx11.hpp +++ b/boost/bind/detail/requires_cxx11.hpp @@ -15,7 +15,7 @@ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Bind 1.82 and will be removed in Boost.Bind 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.Bind 1.82 and will be removed in Boost.Bind 1.84. Please open an issue in https://github.com/boostorg/bind if you want it retained.") #endif diff --git a/boost/bind/detail/result_traits.hpp b/boost/bind/detail/result_traits.hpp deleted file mode 100644 index d57d9fd..0000000 --- a/boost/bind/detail/result_traits.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef BOOST_BIND_DETAIL_RESULT_TRAITS_HPP_INCLUDED -#define BOOST_BIND_DETAIL_RESULT_TRAITS_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// bind/detail/result_traits.hpp -// -// boost/bind.hpp support header, return type deduction -// -// Copyright 2006, 2020 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -#include -#include - -#if BOOST_CXX_VERSION >= 201700L -#include -#endif - -namespace boost -{ - -namespace _bi -{ - -template struct result_traits -{ - typedef R type; -}; - -struct unspecified {}; - -template struct result_traits -{ - typedef typename F::result_type type; -}; - -template struct result_traits< unspecified, reference_wrapper > -{ - typedef typename F::result_type type; -}; - -#if BOOST_CXX_VERSION >= 201700L - -template struct result_traits< unspecified, std::plus > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::minus > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::multiplies > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::divides > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::modulus > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::negate > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::equal_to > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::not_equal_to > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::greater > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::less > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::greater_equal > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::less_equal > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::logical_and > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::logical_or > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::logical_not > -{ - typedef bool type; -}; - -template struct result_traits< unspecified, std::bit_and > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::bit_or > -{ - typedef T type; -}; - -template struct result_traits< unspecified, std::bit_xor > -{ - typedef T type; -}; - -#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 40900 - -// libstdc++ 4.8 and below don't have std::bit_not - -#else - -template struct result_traits< unspecified, std::bit_not > -{ - typedef T type; -}; - -#endif - -#endif - -} // namespace _bi - -} // namespace boost - -#endif // #ifndef BOOST_BIND_DETAIL_RESULT_TRAITS_HPP_INCLUDED diff --git a/boost/bind/placeholders.hpp b/boost/bind/placeholders.hpp deleted file mode 100644 index 5e4b96d..0000000 --- a/boost/bind/placeholders.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED -#define BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// bind/placeholders.hpp - _N definitions -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// Copyright 2015 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -#include -#include - -namespace boost -{ - -namespace placeholders -{ - -#if defined(BOOST_BORLANDC) || defined(__GNUC__) && (__GNUC__ < 4) - -inline boost::arg<1> _1() { return boost::arg<1>(); } -inline boost::arg<2> _2() { return boost::arg<2>(); } -inline boost::arg<3> _3() { return boost::arg<3>(); } -inline boost::arg<4> _4() { return boost::arg<4>(); } -inline boost::arg<5> _5() { return boost::arg<5>(); } -inline boost::arg<6> _6() { return boost::arg<6>(); } -inline boost::arg<7> _7() { return boost::arg<7>(); } -inline boost::arg<8> _8() { return boost::arg<8>(); } -inline boost::arg<9> _9() { return boost::arg<9>(); } - -#elif !defined(BOOST_NO_CXX17_INLINE_VARIABLES) - -BOOST_INLINE_CONSTEXPR boost::arg<1> _1; -BOOST_INLINE_CONSTEXPR boost::arg<2> _2; -BOOST_INLINE_CONSTEXPR boost::arg<3> _3; -BOOST_INLINE_CONSTEXPR boost::arg<4> _4; -BOOST_INLINE_CONSTEXPR boost::arg<5> _5; -BOOST_INLINE_CONSTEXPR boost::arg<6> _6; -BOOST_INLINE_CONSTEXPR boost::arg<7> _7; -BOOST_INLINE_CONSTEXPR boost::arg<8> _8; -BOOST_INLINE_CONSTEXPR boost::arg<9> _9; - -#else - -BOOST_STATIC_CONSTEXPR boost::arg<1> _1; -BOOST_STATIC_CONSTEXPR boost::arg<2> _2; -BOOST_STATIC_CONSTEXPR boost::arg<3> _3; -BOOST_STATIC_CONSTEXPR boost::arg<4> _4; -BOOST_STATIC_CONSTEXPR boost::arg<5> _5; -BOOST_STATIC_CONSTEXPR boost::arg<6> _6; -BOOST_STATIC_CONSTEXPR boost::arg<7> _7; -BOOST_STATIC_CONSTEXPR boost::arg<8> _8; -BOOST_STATIC_CONSTEXPR boost::arg<9> _9; - -#endif - -} // namespace placeholders - -} // namespace boost - -#endif // #ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED diff --git a/boost/bind/std_placeholders.hpp b/boost/bind/std_placeholders.hpp deleted file mode 100644 index 125ff24..0000000 --- a/boost/bind/std_placeholders.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BOOST_BIND_STD_PLACEHOLDERS_HPP_INCLUDED -#define BOOST_BIND_STD_PLACEHOLDERS_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// Copyright 2021 Peter Dimov -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include -#include -#include - -#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) && !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) - -#include -#include - -namespace boost -{ - -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 1 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 2 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 3 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 4 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 5 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 6 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 7 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 8 }; }; -template<> struct is_placeholder< typename std::decay::type > { enum _vt { value = 9 }; }; - -} // namespace boost - -#endif - -#endif // #ifndef BOOST_BIND_STD_PLACEHOLDERS_HPP_INCLUDED diff --git a/boost/bind/storage.hpp b/boost/bind/storage.hpp deleted file mode 100644 index 2ab0db1..0000000 --- a/boost/bind/storage.hpp +++ /dev/null @@ -1,476 +0,0 @@ -#ifndef BOOST_BIND_STORAGE_HPP_INCLUDED -#define BOOST_BIND_STORAGE_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// -// bind/storage.hpp -// -// boost/bind.hpp support header, optimized storage -// -// Copyright (c) 2006 Peter Dimov -// -// Distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt -// -// See http://www.boost.org/libs/bind/bind.html for documentation. -// - -#include -#include -#include - -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4512) // assignment operator could not be generated -#endif - -namespace boost -{ - -namespace _bi -{ - -// 1 - -template struct storage1 -{ - explicit storage1( A1 a1 ): a1_( a1 ) {} - - template void accept(V & v) const - { - BOOST_BIND_VISIT_EACH(v, a1_, 0); - } - - A1 a1_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_BORLANDC ) - -template struct storage1< boost::arg > -{ - explicit storage1( boost::arg ) {} - - template void accept(V &) const { } - - static boost::arg a1_() { return boost::arg(); } -}; - -template struct storage1< boost::arg (*) () > -{ - explicit storage1( boost::arg (*) () ) {} - - template void accept(V &) const { } - - static boost::arg a1_() { return boost::arg(); } -}; - -#endif - -// 2 - -template struct storage2: public storage1 -{ - typedef storage1 inherited; - - storage2( A1 a1, A2 a2 ): storage1( a1 ), a2_( a2 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a2_, 0); - } - - A2 a2_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage2< A1, boost::arg >: public storage1 -{ - typedef storage1 inherited; - - storage2( A1 a1, boost::arg ): storage1( a1 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a2_() { return boost::arg(); } -}; - -template struct storage2< A1, boost::arg (*) () >: public storage1 -{ - typedef storage1 inherited; - - storage2( A1 a1, boost::arg (*) () ): storage1( a1 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a2_() { return boost::arg(); } -}; - -#endif - -// 3 - -template struct storage3: public storage2< A1, A2 > -{ - typedef storage2 inherited; - - storage3( A1 a1, A2 a2, A3 a3 ): storage2( a1, a2 ), a3_( a3 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a3_, 0); - } - - A3 a3_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage3< A1, A2, boost::arg >: public storage2< A1, A2 > -{ - typedef storage2 inherited; - - storage3( A1 a1, A2 a2, boost::arg ): storage2( a1, a2 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a3_() { return boost::arg(); } -}; - -template struct storage3< A1, A2, boost::arg (*) () >: public storage2< A1, A2 > -{ - typedef storage2 inherited; - - storage3( A1 a1, A2 a2, boost::arg (*) () ): storage2( a1, a2 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a3_() { return boost::arg(); } -}; - -#endif - -// 4 - -template struct storage4: public storage3< A1, A2, A3 > -{ - typedef storage3 inherited; - - storage4( A1 a1, A2 a2, A3 a3, A4 a4 ): storage3( a1, a2, a3 ), a4_( a4 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a4_, 0); - } - - A4 a4_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage4< A1, A2, A3, boost::arg >: public storage3< A1, A2, A3 > -{ - typedef storage3 inherited; - - storage4( A1 a1, A2 a2, A3 a3, boost::arg ): storage3( a1, a2, a3 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a4_() { return boost::arg(); } -}; - -template struct storage4< A1, A2, A3, boost::arg (*) () >: public storage3< A1, A2, A3 > -{ - typedef storage3 inherited; - - storage4( A1 a1, A2 a2, A3 a3, boost::arg (*) () ): storage3( a1, a2, a3 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a4_() { return boost::arg(); } -}; - -#endif - -// 5 - -template struct storage5: public storage4< A1, A2, A3, A4 > -{ - typedef storage4 inherited; - - storage5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): storage4( a1, a2, a3, a4 ), a5_( a5 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a5_, 0); - } - - A5 a5_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage5< A1, A2, A3, A4, boost::arg >: public storage4< A1, A2, A3, A4 > -{ - typedef storage4 inherited; - - storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg ): storage4( a1, a2, a3, a4 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a5_() { return boost::arg(); } -}; - -template struct storage5< A1, A2, A3, A4, boost::arg (*) () >: public storage4< A1, A2, A3, A4 > -{ - typedef storage4 inherited; - - storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg (*) () ): storage4( a1, a2, a3, a4 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a5_() { return boost::arg(); } -}; - -#endif - -// 6 - -template struct storage6: public storage5< A1, A2, A3, A4, A5 > -{ - typedef storage5 inherited; - - storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): storage5( a1, a2, a3, a4, a5 ), a6_( a6 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a6_, 0); - } - - A6 a6_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage6< A1, A2, A3, A4, A5, boost::arg >: public storage5< A1, A2, A3, A4, A5 > -{ - typedef storage5 inherited; - - storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg ): storage5( a1, a2, a3, a4, a5 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a6_() { return boost::arg(); } -}; - -template struct storage6< A1, A2, A3, A4, A5, boost::arg (*) () >: public storage5< A1, A2, A3, A4, A5 > -{ - typedef storage5 inherited; - - storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg (*) () ): storage5( a1, a2, a3, a4, a5 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a6_() { return boost::arg(); } -}; - -#endif - -// 7 - -template struct storage7: public storage6< A1, A2, A3, A4, A5, A6 > -{ - typedef storage6 inherited; - - storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): storage6( a1, a2, a3, a4, a5, a6 ), a7_( a7 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a7_, 0); - } - - A7 a7_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage7< A1, A2, A3, A4, A5, A6, boost::arg >: public storage6< A1, A2, A3, A4, A5, A6 > -{ - typedef storage6 inherited; - - storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg ): storage6( a1, a2, a3, a4, a5, a6 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a7_() { return boost::arg(); } -}; - -template struct storage7< A1, A2, A3, A4, A5, A6, boost::arg (*) () >: public storage6< A1, A2, A3, A4, A5, A6 > -{ - typedef storage6 inherited; - - storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg (*) () ): storage6( a1, a2, a3, a4, a5, a6 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a7_() { return boost::arg(); } -}; - -#endif - -// 8 - -template struct storage8: public storage7< A1, A2, A3, A4, A5, A6, A7 > -{ - typedef storage7 inherited; - - storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): storage7( a1, a2, a3, a4, a5, a6, a7 ), a8_( a8 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a8_, 0); - } - - A8 a8_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg >: public storage7< A1, A2, A3, A4, A5, A6, A7 > -{ - typedef storage7 inherited; - - storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg ): storage7( a1, a2, a3, a4, a5, a6, a7 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a8_() { return boost::arg(); } -}; - -template struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg (*) () >: public storage7< A1, A2, A3, A4, A5, A6, A7 > -{ - typedef storage7 inherited; - - storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg (*) () ): storage7( a1, a2, a3, a4, a5, a6, a7 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a8_() { return boost::arg(); } -}; - -#endif - -// 9 - -template struct storage9: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > -{ - typedef storage8 inherited; - - storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ), a9_( a9 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - BOOST_BIND_VISIT_EACH(v, a9_, 0); - } - - A9 a9_; -}; - -#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) - -template struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > -{ - typedef storage8 inherited; - - storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a9_() { return boost::arg(); } -}; - -template struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg (*) () >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 > -{ - typedef storage8 inherited; - - storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg (*) () ): storage8( a1, a2, a3, a4, a5, a6, a7, a8 ) {} - - template void accept(V & v) const - { - inherited::accept(v); - } - - static boost::arg a9_() { return boost::arg(); } -}; - -#endif - -} // namespace _bi - -} // namespace boost - -#ifdef BOOST_MSVC -# pragma warning(default: 4512) // assignment operator could not be generated -# pragma warning(pop) -#endif - -#endif // #ifndef BOOST_BIND_STORAGE_HPP_INCLUDED diff --git a/boost/blank.hpp b/boost/blank.hpp deleted file mode 100644 index 918723c..0000000 --- a/boost/blank.hpp +++ /dev/null @@ -1,106 +0,0 @@ -//----------------------------------------------------------------------------- -// boost blank.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_BLANK_HPP -#define BOOST_BLANK_HPP - -#include "boost/blank_fwd.hpp" - -#if !defined(BOOST_NO_IOSTREAM) -#include // for std::basic_ostream forward declare -#include "boost/detail/templated_streams.hpp" -#endif // BOOST_NO_IOSTREAM - -#include "boost/type_traits/integral_constant.hpp" -#include "boost/type_traits/is_empty.hpp" -#include "boost/type_traits/is_pod.hpp" -#include "boost/type_traits/is_stateless.hpp" - -namespace boost { - -struct blank -{ -}; - -// type traits specializations -// - -template <> -struct is_pod< blank > - : boost::true_type -{ -}; - -template <> -struct is_empty< blank > - : boost::true_type -{ -}; - -template <> -struct is_stateless< blank > - : boost::true_type -{ -}; - -// relational operators -// - -inline bool operator==(const blank&, const blank&) -{ - return true; -} - -inline bool operator<=(const blank&, const blank&) -{ - return true; -} - -inline bool operator>=(const blank&, const blank&) -{ - return true; -} - -inline bool operator!=(const blank&, const blank&) -{ - return false; -} - -inline bool operator<(const blank&, const blank&) -{ - return false; -} - -inline bool operator>(const blank&, const blank&) -{ - return false; -} - -// streaming support -// -#if !defined(BOOST_NO_IOSTREAM) - -BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) -inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<( - BOOST_TEMPLATED_STREAM(ostream, E,T)& out - , const blank& - ) -{ - // (output nothing) - return out; -} - -#endif // BOOST_NO_IOSTREAM - -} // namespace boost - -#endif // BOOST_BLANK_HPP diff --git a/boost/blank_fwd.hpp b/boost/blank_fwd.hpp deleted file mode 100644 index 8bfe97c..0000000 --- a/boost/blank_fwd.hpp +++ /dev/null @@ -1,22 +0,0 @@ -//----------------------------------------------------------------------------- -// boost blank_fwd.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_BLANK_FWD_HPP -#define BOOST_BLANK_FWD_HPP - -namespace boost { - -struct blank; - -} // namespace boost - -#endif // BOOST_BLANK_FWD_HPP diff --git a/boost/chrono/detail/requires_cxx11.hpp b/boost/chrono/detail/requires_cxx11.hpp index bb83105..6f55ae4 100644 --- a/boost/chrono/detail/requires_cxx11.hpp +++ b/boost/chrono/detail/requires_cxx11.hpp @@ -16,7 +16,7 @@ defined(BOOST_NO_CXX11_HDR_CHRONO) || \ defined(BOOST_NO_CXX11_HDR_RATIO) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Chrono 1.82 and will be removed in Boost.Chrono 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.Chrono 1.82 and will be removed in Boost.Chrono 1.84.") #endif diff --git a/boost/chrono/duration.hpp b/boost/chrono/duration.hpp index aceb732..3659cc2 100644 --- a/boost/chrono/duration.hpp +++ b/boost/chrono/duration.hpp @@ -47,7 +47,7 @@ time2_demo contained this comment: #include #include -#include +#include #include #include diff --git a/boost/circular_buffer.hpp b/boost/circular_buffer.hpp deleted file mode 100644 index aa8a2e5..0000000 --- a/boost/circular_buffer.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// Circular buffer library header file. - -// Copyright (c) 2003-2008 Jan Gaspar - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See www.boost.org/libs/circular_buffer for documentation. - -/*! @file -Includes -*/ - -#if !defined(BOOST_CIRCULAR_BUFFER_HPP) -#define BOOST_CIRCULAR_BUFFER_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#include -#include -#include - -/*! Debug support control. */ -#if !defined(BOOST_CB_ENABLE_DEBUG) - #define BOOST_CB_ENABLE_DEBUG 0 -#endif - -/*! INTERNAL ONLY */ -#if BOOST_CB_ENABLE_DEBUG - #include - #define BOOST_CB_ASSERT(Expr) BOOST_ASSERT(Expr) -#else - #define BOOST_CB_ASSERT(Expr) ((void)0) -#endif - -/*! INTERNAL ONLY */ -#if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0550) || BOOST_WORKAROUND(__MWERKS__, <= 0x2407) - #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) ((void)0) -#else - #include - #include - #define BOOST_CB_IS_CONVERTIBLE(Iterator, Type) \ - BOOST_STATIC_ASSERT((is_convertible::value_type, Type>::value)) -#endif - -/*! INTERNAL ONLY */ -#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) - #define BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS BOOST_STATIC_ASSERT(false); -#else - #define BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS ((void)0); -#endif - -#include -#include -#include -#include - -#undef BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS -#undef BOOST_CB_IS_CONVERTIBLE -#undef BOOST_CB_ASSERT - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_HPP) diff --git a/boost/circular_buffer/base.hpp b/boost/circular_buffer/base.hpp deleted file mode 100644 index 4744154..0000000 --- a/boost/circular_buffer/base.hpp +++ /dev/null @@ -1,3134 +0,0 @@ -// Implementation of the base circular buffer. - -// Copyright (c) 2003-2008 Jan Gaspar -// Copyright (c) 2013 Paul A. Bristow // Doxygen comments changed. -// Copyright (c) 2013 Antony Polukhin // Move semantics implementation. - -// Copyright 2014,2018 Glen Joseph Fernandes -// (glenjofe@gmail.com) - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP) -#define BOOST_CIRCULAR_BUFFER_BASE_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) - #include -#endif - -namespace boost { - -/*! - \class circular_buffer - \brief Circular buffer - a STL compliant container. - \tparam T The type of the elements stored in the circular_buffer. - \par Type Requirements T - The T has to be - SGIAssignable (SGI STL defined combination of - Assignable and CopyConstructible). - Moreover T has to be - DefaultConstructible if supplied as a default parameter when invoking some of the - circular_buffer's methods e.g. - insert(iterator pos, const value_type& item = %value_type()). And - EqualityComparable and/or - LessThanComparable if the circular_buffer - will be compared with another container. - \tparam Alloc The allocator type used for all internal memory management. - \par Type Requirements Alloc - The Alloc has to meet the allocator requirements imposed by STL. - \par Default Alloc - std::allocator - - For detailed documentation of the circular_buffer visit: - http://www.boost.org/libs/circular_buffer/doc/circular_buffer.html -*/ -template -class circular_buffer -: -/*! \cond */ -#if BOOST_CB_ENABLE_DEBUG -public cb_details::debug_iterator_registry, -#endif -/*! \endcond */ -private empty_value -{ - typedef empty_value base; - - // Requirements - //BOOST_CLASS_REQUIRE(T, boost, SGIAssignableConcept); - - - //BOOST_CONCEPT_ASSERT((Assignable)); - //BOOST_CONCEPT_ASSERT((CopyConstructible)); - //BOOST_CONCEPT_ASSERT((DefaultConstructible)); - - // Required if the circular_buffer will be compared with anther container. - //BOOST_CONCEPT_ASSERT((EqualityComparable)); - //BOOST_CONCEPT_ASSERT((LessThanComparable)); - -public: -// Basic types - - //! The type of this circular_buffer. - typedef circular_buffer this_type; - - //! The type of elements stored in the circular_buffer. - typedef typename Alloc::value_type value_type; - - //! A pointer to an element. - typedef typename allocator_pointer::type pointer; - - //! A const pointer to the element. - typedef typename allocator_const_pointer::type const_pointer; - - //! A reference to an element. - typedef value_type& reference; - - //! A const reference to an element. - typedef const value_type& const_reference; - - //! The distance type. - /*! - (A signed integral type used to represent the distance between two iterators.) - */ - typedef typename allocator_difference_type::type difference_type; - - //! The size type. - /*! - (An unsigned integral type that can represent any non-negative value of the container's distance type.) - */ - typedef typename allocator_size_type::type size_type; - - //! The type of an allocator used in the circular_buffer. - typedef Alloc allocator_type; - -// Iterators - - //! A const (random access) iterator used to iterate through the circular_buffer. - typedef cb_details::iterator< circular_buffer, cb_details::const_traits > const_iterator; - - //! A (random access) iterator used to iterate through the circular_buffer. - typedef cb_details::iterator< circular_buffer, cb_details::nonconst_traits > iterator; - - //! A const iterator used to iterate backwards through a circular_buffer. - typedef std::reverse_iterator const_reverse_iterator; - - //! An iterator used to iterate backwards through a circular_buffer. - typedef std::reverse_iterator reverse_iterator; - -// Container specific types - - //! An array range. - /*! - (A typedef for the std::pair where - its first element is a pointer to a beginning of an array and its second element represents - a size of the array.) - */ - typedef std::pair array_range; - - //! A range of a const array. - /*! - (A typedef for the std::pair where - its first element is a pointer to a beginning of a const array and its second element represents - a size of the const array.) - */ - typedef std::pair const_array_range; - - //! The capacity type. - /*! - (Same as size_type - defined for consistency with the __cbso class. - - */ - // circular_buffer_space_optimized.) - - typedef size_type capacity_type; - -// Helper types - - //! A type representing the "best" way to pass the value_type to a method. - typedef const value_type& param_value_type; - - //! A type representing rvalue from param type. - //! On compilers without rvalue references support this type is the Boost.Moves type used for emulation. - typedef BOOST_RV_REF(value_type) rvalue_type; - -private: -// Member variables - - //! The internal buffer used for storing elements in the circular buffer. - pointer m_buff; - - //! The internal buffer's end (end of the storage space). - pointer m_end; - - //! The virtual beginning of the circular buffer. - pointer m_first; - - //! The virtual end of the circular buffer (one behind the last element). - pointer m_last; - - //! The number of items currently stored in the circular buffer. - size_type m_size; - -// Friends -#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - friend iterator; - friend const_iterator; -#else - template friend struct cb_details::iterator; -#endif - -public: -// Allocator - - //! Get the allocator. - /*! - \return The allocator. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa get_allocator() for obtaining an allocator %reference. - */ - allocator_type get_allocator() const BOOST_NOEXCEPT { return alloc(); } - - //! Get the allocator reference. - /*! - \return A reference to the allocator. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \note This method was added in order to optimize obtaining of the allocator with a state, - although use of stateful allocators in STL is discouraged. - \sa get_allocator() const - */ - allocator_type& get_allocator() BOOST_NOEXCEPT { return alloc(); } - -// Element access - - //! Get the iterator pointing to the beginning of the circular_buffer. - /*! - \return A random access iterator pointing to the first element of the circular_buffer. If the - circular_buffer is empty it returns an iterator equal to the one returned by - end(). - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa end(), rbegin(), rend() - */ - iterator begin() BOOST_NOEXCEPT { return iterator(this, empty() ? 0 : m_first); } - - //! Get the iterator pointing to the end of the circular_buffer. - /*! - \return A random access iterator pointing to the element "one behind" the last element of the - circular_buffer. If the circular_buffer is empty it returns an iterator equal to - the one returned by begin(). - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa begin(), rbegin(), rend() - */ - iterator end() BOOST_NOEXCEPT { return iterator(this, 0); } - - //! Get the const iterator pointing to the beginning of the circular_buffer. - /*! - \return A const random access iterator pointing to the first element of the circular_buffer. If - the circular_buffer is empty it returns an iterator equal to the one returned by - end() const. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa end() const, rbegin() const, rend() const - */ - const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(this, empty() ? 0 : m_first); } - - const_iterator cbegin() const BOOST_NOEXCEPT { return begin(); } - //! Get the const iterator pointing to the end of the circular_buffer. - /*! - \return A const random access iterator pointing to the element "one behind" the last element of the - circular_buffer. If the circular_buffer is empty it returns an iterator equal to - the one returned by begin() const const. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa begin() const, rbegin() const, rend() const - */ - const_iterator end() const BOOST_NOEXCEPT { return const_iterator(this, 0); } - - const_iterator cend() const BOOST_NOEXCEPT { return end(); } - //! Get the iterator pointing to the beginning of the "reversed" circular_buffer. - /*! - \return A reverse random access iterator pointing to the last element of the circular_buffer. - If the circular_buffer is empty it returns an iterator equal to the one returned by - rend(). - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa rend(), begin(), end() - */ - reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); } - - //! Get the iterator pointing to the end of the "reversed" circular_buffer. - /*! - \return A reverse random access iterator pointing to the element "one before" the first element of the - circular_buffer. If the circular_buffer is empty it returns an iterator equal to - the one returned by rbegin(). - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa rbegin(), begin(), end() - */ - reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); } - - //! Get the const iterator pointing to the beginning of the "reversed" circular_buffer. - /*! - \return A const reverse random access iterator pointing to the last element of the - circular_buffer. If the circular_buffer is empty it returns an iterator equal - to the one returned by rend() const. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa rend() const, begin() const, end() const - */ - const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } - - //! Get the const iterator pointing to the end of the "reversed" circular_buffer. - /*! - \return A const reverse random access iterator pointing to the element "one before" the first element of the - circular_buffer. If the circular_buffer is empty it returns an iterator equal - to the one returned by rbegin() const. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa rbegin() const, begin() const, end() const - */ - const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } - - //! Get the element at the index position. - /*! - \pre 0 \<= index \&\& index \< size() - \param index The position of the element. - \return A reference to the element at the index position. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa at() - */ - reference operator [] (size_type index) { - BOOST_CB_ASSERT(index < size()); // check for invalid index - return *add(m_first, index); - } - - //! Get the element at the index position. - /*! - \pre 0 \<= index \&\& index \< size() - \param index The position of the element. - \return A const reference to the element at the index position. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link at(size_type)const at() const \endlink - */ - const_reference operator [] (size_type index) const { - BOOST_CB_ASSERT(index < size()); // check for invalid index - return *add(m_first, index); - } - - //! Get the element at the index position. - /*! - \param index The position of the element. - \return A reference to the element at the index position. - \throws std::out_of_range when the index is invalid (when - index >= size()). - \par Exception Safety - Strong. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link operator[](size_type) operator[] \endlink - */ - reference at(size_type index) { - check_position(index); - return (*this)[index]; - } - - //! Get the element at the index position. - /*! - \param index The position of the element. - \return A const reference to the element at the index position. - \throws std::out_of_range when the index is invalid (when - index >= size()). - \par Exception Safety - Strong. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link operator[](size_type)const operator[] const \endlink - */ - const_reference at(size_type index) const { - check_position(index); - return (*this)[index]; - } - - //! Get the first element. - /*! - \pre !empty() - \return A reference to the first element of the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa back() - */ - reference front() { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) - return *m_first; - } - - //! Get the last element. - /*! - \pre !empty() - \return A reference to the last element of the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa front() - */ - reference back() { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) - return *((m_last == m_buff ? m_end : m_last) - 1); - } - - //! Get the first element. - /*! - \pre !empty() - \return A const reference to the first element of the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa back() const - */ - const_reference front() const { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) - return *m_first; - } - - //! Get the last element. - /*! - \pre !empty() - \return A const reference to the last element of the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa front() const - */ - const_reference back() const { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) - return *((m_last == m_buff ? m_end : m_last) - 1); - } - - //! Get the first continuous array of the internal buffer. - /*! - This method in combination with array_two() can be useful when passing the stored data into - a legacy C API as an array. Suppose there is a circular_buffer of capacity 10, containing 7 - characters 'a', 'b', ..., 'g' where buff[0] == 'a', buff[1] == 'b', - ... and buff[6] == 'g':

- circular_buffer buff(10);

- The internal representation is often not linear and the state of the internal buffer may look like this:
-
- |e|f|g| | | |a|b|c|d|
- end ___^
- begin _______^


- - where |a|b|c|d| represents the "array one", |e|f|g| represents the "array two" and - | | | | is a free space.
- Now consider a typical C style function for writing data into a file:

- int write(int file_desc, char* buff, int num_bytes);

- There are two ways how to write the content of the circular_buffer into a file. Either relying - on array_one() and array_two() methods and calling the write function twice:

- array_range ar = buff.array_one();
- write(file_desc, ar.first, ar.second);
- ar = buff.array_two();
- write(file_desc, ar.first, ar.second);


- Or relying on the linearize() method:

- write(file_desc, buff.linearize(), buff.size());

- Since the complexity of array_one() and array_two() methods is constant the first - option is suitable when calling the write method is "cheap". On the other hand the second option is more - suitable when calling the write method is more "expensive" than calling the linearize() method - whose complexity is linear. - \return The array range of the first continuous array of the internal buffer. In the case the - circular_buffer is empty the size of the returned array is 0. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \warning In general invoking any method which modifies the internal state of the circular_buffer may - delinearize the internal buffer and invalidate the array ranges returned by array_one() - and array_two() (and their const versions). - \note In the case the internal buffer is linear e.g. |a|b|c|d|e|f|g| | | | the "array one" is - represented by |a|b|c|d|e|f|g| and the "array two" does not exist (the - array_two() method returns an array with the size 0). - \sa array_two(), linearize() - */ - array_range array_one() { - return array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first); - } - - //! Get the second continuous array of the internal buffer. - /*! - This method in combination with array_one() can be useful when passing the stored data into - a legacy C API as an array. - \return The array range of the second continuous array of the internal buffer. In the case the internal buffer - is linear or the circular_buffer is empty the size of the returned array is - 0. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa array_one() - */ - array_range array_two() { - return array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0); - } - - //! Get the first continuous array of the internal buffer. - /*! - This method in combination with array_two() const can be useful when passing the stored data into - a legacy C API as an array. - \return The array range of the first continuous array of the internal buffer. In the case the - circular_buffer is empty the size of the returned array is 0. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa array_two() const; array_one() for more details how to pass data into a legacy C - API. - */ - const_array_range array_one() const { - return const_array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first); - } - - //! Get the second continuous array of the internal buffer. - /*! - This method in combination with array_one() const can be useful when passing the stored data into - a legacy C API as an array. - \return The array range of the second continuous array of the internal buffer. In the case the internal buffer - is linear or the circular_buffer is empty the size of the returned array is - 0. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa array_one() const - */ - const_array_range array_two() const { - return const_array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0); - } - - //! Linearize the internal buffer into a continuous array. - /*! - This method can be useful when passing the stored data into a legacy C API as an array. - \post \&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1] - \return A pointer to the beginning of the array or 0 if empty. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()); does not invalidate any iterators if the postcondition (the Effect) is already - met prior calling this method. - \par Complexity - Linear (in the size of the circular_buffer); constant if the postcondition (the - Effect) is already met. - \warning In general invoking any method which modifies the internal state of the circular_buffer - may delinearize the internal buffer and invalidate the returned pointer. - \sa array_one() and array_two() for the other option how to pass data into a legacy - C API; is_linearized(), rotate(const_iterator) - */ - pointer linearize() { - if (empty()) - return 0; - if (m_first < m_last || m_last == m_buff) - return m_first; - pointer src = m_first; - pointer dest = m_buff; - size_type moved = 0; - size_type constructed = 0; - BOOST_TRY { - for (pointer first = m_first; dest < src; src = first) { - for (size_type ii = 0; src < m_end; ++src, ++dest, ++moved, ++ii) { - if (moved == size()) { - first = dest; - break; - } - if (dest == first) { - first += ii; - break; - } - if (is_uninitialized(dest)) { - boost::allocator_construct(alloc(), boost::to_address(dest), boost::move_if_noexcept(*src)); - ++constructed; - } else { - value_type tmp = boost::move_if_noexcept(*src); - replace(src, boost::move_if_noexcept(*dest)); - replace(dest, boost::move(tmp)); - } - } - } - } BOOST_CATCH(...) { - m_last += constructed; - m_size += constructed; - BOOST_RETHROW - } - BOOST_CATCH_END - for (src = m_end - constructed; src < m_end; ++src) - destroy_item(src); - m_first = m_buff; - m_last = add(m_buff, size()); -#if BOOST_CB_ENABLE_DEBUG - invalidate_iterators_except(end()); -#endif - return m_buff; - } - - //! Is the circular_buffer linearized? - /*! - \return true if the internal buffer is linearized into a continuous array (i.e. the - circular_buffer meets a condition - \&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1]); - false otherwise. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa linearize(), array_one(), array_two() - */ - bool is_linearized() const BOOST_NOEXCEPT { return m_first < m_last || m_last == m_buff; } - - //! Rotate elements in the circular_buffer. - /*! - A more effective implementation of - std::rotate. - \pre new_begin is a valid iterator pointing to the circular_buffer except its - end. - \post Before calling the method suppose:

- m == std::distance(new_begin, end())
n == std::distance(begin(), new_begin) -
val_0 == *new_begin, val_1 == *(new_begin + 1), ... val_m == *(new_begin + m)
- val_r1 == *(new_begin - 1), val_r2 == *(new_begin - 2), ... val_rn == *(new_begin - n)
-
then after call to the method:

- val_0 == (*this)[0] \&\& val_1 == (*this)[1] \&\& ... \&\& val_m == (*this)[m - 1] \&\& val_r1 == - (*this)[m + n - 1] \&\& val_r2 == (*this)[m + n - 2] \&\& ... \&\& val_rn == (*this)[m] - \param new_begin The new beginning. - \throws See Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the circular_buffer is full or new_begin points to - begin() or if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - If m \< n invalidates iterators pointing to the last m elements - (including new_begin, but not iterators equal to end()) else invalidates - iterators pointing to the first n elements; does not invalidate any iterators if the - circular_buffer is full. - \par Complexity - Linear (in (std::min)(m, n)); constant if the circular_buffer is full. - \sa std::rotate - */ - void rotate(const_iterator new_begin) { - BOOST_CB_ASSERT(new_begin.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(new_begin.m_it != 0); // check for iterator pointing to end() - if (full()) { - m_first = m_last = const_cast(new_begin.m_it); - } else { - difference_type m = end() - new_begin; - difference_type n = new_begin - begin(); - if (m < n) { - for (; m > 0; --m) { - push_front(boost::move_if_noexcept(back())); - pop_back(); - } - } else { - for (; n > 0; --n) { - push_back(boost::move_if_noexcept(front())); - pop_front(); - } - } - } - } - -// Size and capacity - - //! Get the number of elements currently stored in the circular_buffer. - /*! - \return The number of elements stored in the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa capacity(), max_size(), reserve(), - \link resize() resize(size_type, const_reference)\endlink - */ - size_type size() const BOOST_NOEXCEPT { return m_size; } - - /*! \brief Get the largest possible size or capacity of the circular_buffer. (It depends on - allocator's %max_size()). - \return The maximum size/capacity the circular_buffer can be set to. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa size(), capacity(), reserve() - */ - size_type max_size() const BOOST_NOEXCEPT { - return (std::min)(boost::allocator_max_size(alloc()), (std::numeric_limits::max)()); - } - - //! Is the circular_buffer empty? - /*! - \return true if there are no elements stored in the circular_buffer; - false otherwise. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa full() - */ - bool empty() const BOOST_NOEXCEPT { return size() == 0; } - - //! Is the circular_buffer full? - /*! - \return true if the number of elements stored in the circular_buffer - equals the capacity of the circular_buffer; false otherwise. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa empty() - */ - bool full() const BOOST_NOEXCEPT { return capacity() == size(); } - - /*! \brief Get the maximum number of elements which can be inserted into the circular_buffer without - overwriting any of already stored elements. - \return capacity() - size() - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa capacity(), size(), max_size() - */ - size_type reserve() const BOOST_NOEXCEPT { return capacity() - size(); } - - //! Get the capacity of the circular_buffer. - /*! - \return The maximum number of elements which can be stored in the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer). - \sa reserve(), size(), max_size(), - set_capacity(capacity_type) - */ - capacity_type capacity() const BOOST_NOEXCEPT { return m_end - m_buff; } - - //! Change the capacity of the circular_buffer. - /*! - \pre If T is a move only type, then compiler shall support noexcept modifiers - and move constructor of T must be marked with it (must not throw exceptions). - \post capacity() == new_capacity \&\& size() \<= new_capacity

- If the current number of elements stored in the circular_buffer is greater than the desired - new capacity then number of [size() - new_capacity] last elements will be removed and - the new size will be equal to new_capacity. - \param new_capacity The new capacity. - \throws "An allocation error" if memory is exhausted, (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()) if the new capacity is different from the original. - \par Complexity - Linear (in min[size(), new_capacity]). - \sa rset_capacity(capacity_type), - \link resize() resize(size_type, const_reference)\endlink - */ - void set_capacity(capacity_type new_capacity) { - if (new_capacity == capacity()) - return; - pointer buff = allocate(new_capacity); - iterator b = begin(); - BOOST_TRY { - reset(buff, - cb_details::uninitialized_move_if_noexcept(b, b + (std::min)(new_capacity, size()), buff, alloc()), - new_capacity); - } BOOST_CATCH(...) { - deallocate(buff, new_capacity); - BOOST_RETHROW - } - BOOST_CATCH_END - } - - //! Change the size of the circular_buffer. - /*! - \post size() == new_size \&\& capacity() >= new_size

- If the new size is greater than the current size, copies of item will be inserted at the - back of the of the circular_buffer in order to achieve the desired size. In the case - the resulting size exceeds the current capacity the capacity will be set to new_size.
- If the current number of elements stored in the circular_buffer is greater than the desired - new size then number of [size() - new_size] last elements will be removed. (The - capacity will remain unchanged.) - \param new_size The new size. - \param item The element the circular_buffer will be filled with in order to gain the requested - size. (See the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()) if the new size is greater than the current capacity. Invalidates iterators pointing - to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate - any iterator. - \par Complexity - Linear (in the new size of the circular_buffer). - \sa \link rresize() rresize(size_type, const_reference)\endlink, - set_capacity(capacity_type) - */ - void resize(size_type new_size, param_value_type item = value_type()) { - if (new_size > size()) { - if (new_size > capacity()) - set_capacity(new_size); - insert(end(), new_size - size(), item); - } else { - iterator e = end(); - erase(e - (size() - new_size), e); - } - } - - //! Change the capacity of the circular_buffer. - /*! - \pre If T is a move only type, then compiler shall support noexcept modifiers - and move constructor of T must be marked with it (must not throw exceptions). - \post capacity() == new_capacity \&\& size() \<= new_capacity

- If the current number of elements stored in the circular_buffer is greater than the desired - new capacity then number of [size() - new_capacity] first elements will be removed - and the new size will be equal to new_capacity. - \param new_capacity The new capacity. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()) if the new capacity is different from the original. - \par Complexity - Linear (in min[size(), new_capacity]). - \sa set_capacity(capacity_type), - \link rresize() rresize(size_type, const_reference)\endlink - */ - void rset_capacity(capacity_type new_capacity) { - if (new_capacity == capacity()) - return; - pointer buff = allocate(new_capacity); - iterator e = end(); - BOOST_TRY { - reset(buff, cb_details::uninitialized_move_if_noexcept(e - (std::min)(new_capacity, size()), - e, buff, alloc()), new_capacity); - } BOOST_CATCH(...) { - deallocate(buff, new_capacity); - BOOST_RETHROW - } - BOOST_CATCH_END - } - - //! Change the size of the circular_buffer. - /*! - \post size() == new_size \&\& capacity() >= new_size

- If the new size is greater than the current size, copies of item will be inserted at the - front of the of the circular_buffer in order to achieve the desired size. In the case - the resulting size exceeds the current capacity the capacity will be set to new_size.
- If the current number of elements stored in the circular_buffer is greater than the desired - new size then number of [size() - new_size] first elements will be removed. (The - capacity will remain unchanged.) - \param new_size The new size. - \param item The element the circular_buffer will be filled with in order to gain the requested - size. (See the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()) if the new size is greater than the current capacity. Invalidates iterators pointing - to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate - any iterator. - \par Complexity - Linear (in the new size of the circular_buffer). - \sa \link resize() resize(size_type, const_reference)\endlink, - rset_capacity(capacity_type) - */ - void rresize(size_type new_size, param_value_type item = value_type()) { - if (new_size > size()) { - if (new_size > capacity()) - set_capacity(new_size); - rinsert(begin(), new_size - size(), item); - } else { - rerase(begin(), end() - new_size); - } - } - -// Construction/Destruction - - //! Create an empty circular_buffer with zero capacity. - /*! - \post capacity() == 0 \&\& size() == 0 - \param alloc The allocator. - \throws Nothing. - \par Complexity - Constant. - \warning Since Boost version 1.36 the behaviour of this constructor has changed. Now the constructor does not - allocate any memory and both capacity and size are set to zero. Also note when inserting an element - into a circular_buffer with zero capacity (e.g. by - \link push_back() push_back(const_reference)\endlink or - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink) nothing - will be inserted and the size (as well as capacity) remains zero. - \note You can explicitly set the capacity by calling the set_capacity(capacity_type) method or you - can use the other constructor with the capacity specified. - \sa circular_buffer(capacity_type, const allocator_type& alloc), - set_capacity(capacity_type) - */ - explicit circular_buffer(const allocator_type& alloc = allocator_type()) BOOST_NOEXCEPT - : base(boost::empty_init_t(), alloc), m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0) {} - - //! Create an empty circular_buffer with the specified capacity. - /*! - \post capacity() == buffer_capacity \&\& size() == 0 - \param buffer_capacity The maximum number of elements which can be stored in the circular_buffer. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Complexity - Constant. - */ - explicit circular_buffer(capacity_type buffer_capacity, const allocator_type& alloc = allocator_type()) - : base(boost::empty_init_t(), alloc), m_size(0) { - initialize_buffer(buffer_capacity); - m_first = m_last = m_buff; - } - - /*! \brief Create a full circular_buffer with the specified capacity and filled with n - copies of item. - \post capacity() == n \&\& full() \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\& - (*this)[n - 1] == item - \param n The number of elements the created circular_buffer will be filled with. - \param item The element the created circular_buffer will be filled with. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the n). - */ - circular_buffer(size_type n, param_value_type item, const allocator_type& alloc = allocator_type()) - : base(boost::empty_init_t(), alloc), m_size(n) { - initialize_buffer(n, item); - m_first = m_last = m_buff; - } - - /*! \brief Create a circular_buffer with the specified capacity and filled with n - copies of item. - \pre buffer_capacity >= n - \post capacity() == buffer_capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item - \&\& ... \&\& (*this)[n - 1] == item - \param buffer_capacity The capacity of the created circular_buffer. - \param n The number of elements the created circular_buffer will be filled with. - \param item The element the created circular_buffer will be filled with. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the n). - */ - circular_buffer(capacity_type buffer_capacity, size_type n, param_value_type item, - const allocator_type& alloc = allocator_type()) - : base(boost::empty_init_t(), alloc), m_size(n) { - BOOST_CB_ASSERT(buffer_capacity >= size()); // check for capacity lower than size - initialize_buffer(buffer_capacity, item); - m_first = m_buff; - m_last = buffer_capacity == n ? m_buff : m_buff + n; - } - - //! The copy constructor. - /*! - Creates a copy of the specified circular_buffer. - \post *this == cb - \param cb The circular_buffer to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the size of cb). - */ - circular_buffer(const circular_buffer& cb) - : -#if BOOST_CB_ENABLE_DEBUG - debug_iterator_registry(), -#endif - base(boost::empty_init_t(), cb.get_allocator()), - m_size(cb.size()) { - initialize_buffer(cb.capacity()); - m_first = m_buff; - BOOST_TRY { - m_last = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, alloc()); - } BOOST_CATCH(...) { - deallocate(m_buff, cb.capacity()); - BOOST_RETHROW - } - BOOST_CATCH_END - if (m_last == m_end) - m_last = m_buff; - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - //! The move constructor. - /*! \brief Move constructs a circular_buffer from cb, leaving cb empty. - \pre C++ compiler with rvalue references support. - \post cb.empty() - \param cb circular_buffer to 'steal' value from. - \throws Nothing. - \par Constant. - */ - circular_buffer(circular_buffer&& cb) BOOST_NOEXCEPT - : base(boost::empty_init_t(), cb.get_allocator()), m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0) { - cb.swap(*this); - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - //! Create a full circular_buffer filled with a copy of the range. - /*! - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == std::distance(first, last) \&\& full() \&\& (*this)[0]== *first \&\& - (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] == *(last - 1) - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the std::distance(first, last)). - */ - template - circular_buffer(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) - : base(boost::empty_init_t(), alloc) { - initialize(first, last, is_integral()); - } - - //! Create a circular_buffer with the specified capacity and filled with a copy of the range. - /*! - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\& - (*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\& - (*this)[buffer_capacity - 1] == *(last - 1)

- If the number of items to be copied from the range [first, last) is greater than the - specified buffer_capacity then only elements from the range - [last - buffer_capacity, last) will be copied. - \param buffer_capacity The capacity of the created circular_buffer. - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in std::distance(first, last); in - min[capacity, std::distance(first, last)] if the InputIterator is a - RandomAccessIterator). - */ - template - circular_buffer(capacity_type buffer_capacity, InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()) - : base(boost::empty_init_t(), alloc) { - initialize(buffer_capacity, first, last, is_integral()); - } - - //! The destructor. - /*! - Destroys the circular_buffer. - \throws Nothing. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (including iterators equal to - end()). - \par Complexity - Constant (in the size of the circular_buffer) for scalar types; linear for other types. - \sa clear() - */ - ~circular_buffer() BOOST_NOEXCEPT { - destroy(); -#if BOOST_CB_ENABLE_DEBUG - invalidate_all_iterators(); -#endif - } - -public: -// Assign methods - - //! The assign operator. - /*! - Makes this circular_buffer to become a copy of the specified circular_buffer. - \post *this == cb - \param cb The circular_buffer to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to this circular_buffer (except iterators equal to - end()). - \par Complexity - Linear (in the size of cb). - \sa \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - circular_buffer& operator = (const circular_buffer& cb) { - if (this == &cb) - return *this; - pointer buff = allocate(cb.capacity()); - BOOST_TRY { - reset(buff, cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, alloc()), cb.capacity()); - } BOOST_CATCH(...) { - deallocate(buff, cb.capacity()); - BOOST_RETHROW - } - BOOST_CATCH_END - return *this; - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - /*! \brief Move assigns content of cb to *this, leaving cb empty. - \pre C++ compiler with rvalue references support. - \post cb.empty() - \param cb circular_buffer to 'steal' value from. - \throws Nothing. - \par Complexity - Constant. - */ - circular_buffer& operator = (circular_buffer&& cb) BOOST_NOEXCEPT { - cb.swap(*this); // now `this` holds `cb` - circular_buffer(get_allocator()) // temporary that holds initial `cb` allocator - .swap(cb); // makes `cb` empty - return *this; - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - //! Assign n items into the circular_buffer. - /*! - The content of the circular_buffer will be removed and replaced with n copies of the - item. - \post capacity() == n \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\& - (*this) [n - 1] == item - \param n The number of elements the circular_buffer will be filled with. - \param item The element the circular_buffer will be filled with. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()). - \par Complexity - Linear (in the n). - \sa \link operator=(const circular_buffer&) operator=\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - void assign(size_type n, param_value_type item) { - assign_n(n, n, cb_details::assign_n(n, item, alloc())); - } - - //! Assign n items into the circular_buffer specifying the capacity. - /*! - The capacity of the circular_buffer will be set to the specified value and the content of the - circular_buffer will be removed and replaced with n copies of the item. - \pre capacity >= n - \post capacity() == buffer_capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item - \&\& ... \&\& (*this) [n - 1] == item - \param buffer_capacity The new capacity. - \param n The number of elements the circular_buffer will be filled with. - \param item The element the circular_buffer will be filled with. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()). - \par Complexity - Linear (in the n). - \sa \link operator=(const circular_buffer&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - void assign(capacity_type buffer_capacity, size_type n, param_value_type item) { - BOOST_CB_ASSERT(buffer_capacity >= n); // check for new capacity lower than n - assign_n(buffer_capacity, n, cb_details::assign_n(n, item, alloc())); - } - - //! Assign a copy of the range into the circular_buffer. - /*! - The content of the circular_buffer will be removed and replaced with copies of elements from the - specified range. - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == std::distance(first, last) \&\& size() == std::distance(first, last) \&\& - (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] - == *(last - 1) - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()). - \par Complexity - Linear (in the std::distance(first, last)). - \sa \link operator=(const circular_buffer&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(capacity_type, InputIterator, InputIterator) - */ - template - void assign(InputIterator first, InputIterator last) { - assign(first, last, is_integral()); - } - - //! Assign a copy of the range into the circular_buffer specifying the capacity. - /*! - The capacity of the circular_buffer will be set to the specified value and the content of the - circular_buffer will be removed and replaced with copies of elements from the specified range. - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\& - (*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\& - (*this)[buffer_capacity - 1] == *(last - 1)

- If the number of items to be copied from the range [first, last) is greater than the - specified buffer_capacity then only elements from the range - [last - buffer_capacity, last) will be copied. - \param buffer_capacity The new capacity. - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()). - \par Complexity - Linear (in std::distance(first, last); in - min[capacity, std::distance(first, last)] if the InputIterator is a - RandomAccessIterator). - \sa \link operator=(const circular_buffer&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator) - */ - template - void assign(capacity_type buffer_capacity, InputIterator first, InputIterator last) { - assign(buffer_capacity, first, last, is_integral()); - } - - //! Swap the contents of two circular_buffers. - /*! - \post this contains elements of cb and vice versa; the capacity of this - equals to the capacity of cb and vice versa. - \param cb The circular_buffer whose content will be swapped. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Invalidates all iterators of both circular_buffers. (On the other hand the iterators still - point to the same elements but within another container. If you want to rely on this feature you have to - turn the Debug Support off otherwise an assertion will report an error if such - invalidated iterator is used.) - \par Complexity - Constant (in the size of the circular_buffer). - \sa swap(circular_buffer&, circular_buffer&) - */ - void swap(circular_buffer& cb) BOOST_NOEXCEPT { - swap_allocator(cb, is_stateless()); - adl_move_swap(m_buff, cb.m_buff); - adl_move_swap(m_end, cb.m_end); - adl_move_swap(m_first, cb.m_first); - adl_move_swap(m_last, cb.m_last); - adl_move_swap(m_size, cb.m_size); -#if BOOST_CB_ENABLE_DEBUG - invalidate_all_iterators(); - cb.invalidate_all_iterators(); -#endif - } - -// push and pop -private: - /*! INTERNAL ONLY */ - template - void push_back_impl(ValT item) { - if (full()) { - if (empty()) - return; - replace(m_last, static_cast(item)); - increment(m_last); - m_first = m_last; - } else { - boost::allocator_construct(alloc(), boost::to_address(m_last), static_cast(item)); - increment(m_last); - ++m_size; - } - } - - /*! INTERNAL ONLY */ - template - void push_front_impl(ValT item) { - BOOST_TRY { - if (full()) { - if (empty()) - return; - decrement(m_first); - replace(m_first, static_cast(item)); - m_last = m_first; - } else { - decrement(m_first); - boost::allocator_construct(alloc(), boost::to_address(m_first), static_cast(item)); - ++m_size; - } - } BOOST_CATCH(...) { - increment(m_first); - BOOST_RETHROW - } - BOOST_CATCH_END - } - -public: - //! Insert a new element at the end of the circular_buffer. - /*! - \post if capacity() > 0 then back() == item
- If the circular_buffer is full, the first element will be removed. If the capacity is - 0, nothing will be inserted. - \param item The element to be inserted. - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_front() push_front(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_back(param_value_type item) { - push_back_impl(item); - } - - //! Insert a new element at the end of the circular_buffer using rvalue references or rvalues references emulation. - /*! - \post if capacity() > 0 then back() == item
- If the circular_buffer is full, the first element will be removed. If the capacity is - 0, nothing will be inserted. - \param item The element to be inserted. - \throws Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_front() push_front(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_back(rvalue_type item) { - push_back_impl(boost::move(item)); - } - - //! Insert a new default-constructed element at the end of the circular_buffer. - /*! - \post if capacity() > 0 then back() == item
- If the circular_buffer is full, the first element will be removed. If the capacity is - 0, nothing will be inserted. - \throws Whatever T::T() throws. - Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_front() push_front(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_back() { - value_type temp; - push_back(boost::move(temp)); - } - - //! Insert a new element at the beginning of the circular_buffer. - /*! - \post if capacity() > 0 then front() == item
- If the circular_buffer is full, the last element will be removed. If the capacity is - 0, nothing will be inserted. - \param item The element to be inserted. - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_back() push_back(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_front(param_value_type item) { - push_front_impl(item); - } - - //! Insert a new element at the beginning of the circular_buffer using rvalue references or rvalues references emulation. - /*! - \post if capacity() > 0 then front() == item
- If the circular_buffer is full, the last element will be removed. If the capacity is - 0, nothing will be inserted. - \param item The element to be inserted. - \throws Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_back() push_back(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_front(rvalue_type item) { - push_front_impl(boost::move(item)); - } - - //! Insert a new default-constructed element at the beginning of the circular_buffer. - /*! - \post if capacity() > 0 then front() == item
- If the circular_buffer is full, the last element will be removed. If the capacity is - 0, nothing will be inserted. - \throws Whatever T::T() throws. - Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Does not invalidate any iterators with the exception of iterators pointing to the overwritten element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa \link push_back() push_back(const_reference)\endlink, - pop_back(), pop_front() - */ - void push_front() { - value_type temp; - push_front(boost::move(temp)); - } - - //! Remove the last element from the circular_buffer. - /*! - \pre !empty() - \post The last element is removed from the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Invalidates only iterators pointing to the removed element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa pop_front(), \link push_back() push_back(const_reference)\endlink, - \link push_front() push_front(const_reference)\endlink - */ - void pop_back() { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available) - decrement(m_last); - destroy_item(m_last); - --m_size; - } - - //! Remove the first element from the circular_buffer. - /*! - \pre !empty() - \post The first element is removed from the circular_buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Invalidates only iterators pointing to the removed element. - \par Complexity - Constant (in the size of the circular_buffer). - \sa pop_back(), \link push_back() push_back(const_reference)\endlink, - \link push_front() push_front(const_reference)\endlink - */ - void pop_front() { - BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available) - destroy_item(m_first); - increment(m_first); - --m_size; - } -private: - /*! INTERNAL ONLY */ - template - iterator insert_impl(iterator pos, ValT item) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - iterator b = begin(); - if (full() && pos == b) - return b; - return insert_item(pos, static_cast(item)); - } - -public: -// Insert - - //! Insert an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted at the position pos.
- If the circular_buffer is full, the first element will be overwritten. If the - circular_buffer is full and the pos points to begin(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position where the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - Exceptions of move_if_noexcept(T&). - - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements at the insertion point (including pos) and - iterators behind the insertion point (towards the end; except iterators equal to end()). It - also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(pos, end())). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos, param_value_type item) { - return insert_impl(pos, item); - } - - //! Insert an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted at the position pos.
- If the circular_buffer is full, the first element will be overwritten. If the - circular_buffer is full and the pos points to begin(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position where the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements at the insertion point (including pos) and - iterators behind the insertion point (towards the end; except iterators equal to end()). It - also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(pos, end())). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos, rvalue_type item) { - return insert_impl(pos, boost::move(item)); - } - - //! Insert a default-constructed element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted at the position pos.
- If the circular_buffer is full, the first element will be overwritten. If the - circular_buffer is full and the pos points to begin(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position where the item will be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T() throws. - Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements at the insertion point (including pos) and - iterators behind the insertion point (towards the end; except iterators equal to end()). It - also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(pos, end())). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos) { - value_type temp; - return insert(pos, boost::move(temp)); - } - - //! Insert n copies of the item at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The number of min[n, (pos - begin()) + reserve()] elements will be inserted at the position - pos.
The number of min[pos - begin(), max[0, n - reserve()]] elements will - be overwritten at the beginning of the circular_buffer.
(See Example for the - explanation.) - \param pos An iterator specifying the position where the items will be inserted. - \param n The number of items the to be inserted. - \param item The element whose copies will be inserted. - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements at the insertion point (including pos) and - iterators behind the insertion point (towards the end; except iterators equal to end()). It - also invalidates iterators pointing to the overwritten elements. - \par Complexity - Linear (in min[capacity(), std::distance(pos, end()) + n]). - \par Example - Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may - look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting 5 elements at the position p:

- insert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements - 1 and 2 are overwritten. This is due to the fact the insert operation preserves - the capacity. After insertion the internal buffer looks like this:

|0|0|0|0|3|4|
-
For comparison if the capacity would not be preserved the internal buffer would then result in - |1|2|0|0|0|0|0|3|4|. - \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - void insert(iterator pos, size_type n, param_value_type item) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - if (n == 0) - return; - size_type copy = capacity() - (end() - pos); - if (copy == 0) - return; - if (n > copy) - n = copy; - insert_n(pos, n, cb_details::item_wrapper(item)); - } - - //! Insert the range [first, last) at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end.
- Valid range [first, last) where first and last meet the - requirements of an InputIterator. - \post Elements from the range - [first + max[0, distance(first, last) - (pos - begin()) - reserve()], last) will be - inserted at the position pos.
The number of min[pos - begin(), max[0, - distance(first, last) - reserve()]] elements will be overwritten at the beginning of the - circular_buffer.
(See Example for the explanation.) - \param pos An iterator specifying the position where the range will be inserted. - \param first The beginning of the range to be inserted. - \param last The end of the range to be inserted. - \throws Whatever T::T(const T&) throws if the InputIterator is not a move iterator. - Whatever T::operator = (const T&) throws if the InputIterator is not a move iterator. - Whatever T::T(T&&) throws if the InputIterator is a move iterator. - Whatever T::operator = (T&&) throws if the InputIterator is a move iterator. - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements at the insertion point (including pos) and - iterators behind the insertion point (towards the end; except iterators equal to end()). It - also invalidates iterators pointing to the overwritten elements. - \par Complexity - Linear (in [std::distance(pos, end()) + std::distance(first, last)]; in - min[capacity(), std::distance(pos, end()) + std::distance(first, last)] if the - InputIterator is a - RandomAccessIterator). - \par Example - Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may - look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting a range of elements at the position p:

- int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

- actually only elements 6, 7, 8 and 9 from the - specified range get inserted and elements 1 and 2 are overwritten. This is due - to the fact the insert operation preserves the capacity. After insertion the internal buffer looks like - this:

|6|7|8|9|3|4|

For comparison if the capacity would not be preserved the - internal buffer would then result in |1|2|5|6|7|8|9|3|4|. - \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, \link rinsert(iterator, param_value_type) - rinsert(iterator, value_type)\endlink, \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - template - void insert(iterator pos, InputIterator first, InputIterator last) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - insert(pos, first, last, is_integral()); - } - -private: - /*! INTERNAL ONLY */ - template - iterator rinsert_impl(iterator pos, ValT item) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - if (full() && pos.m_it == 0) - return end(); - if (pos == begin()) { - BOOST_TRY { - decrement(m_first); - construct_or_replace(!full(), m_first, static_cast(item)); - } BOOST_CATCH(...) { - increment(m_first); - BOOST_RETHROW - } - BOOST_CATCH_END - pos.m_it = m_first; - } else { - pointer src = m_first; - pointer dest = m_first; - decrement(dest); - pos.m_it = map_pointer(pos.m_it); - bool construct = !full(); - BOOST_TRY { - while (src != pos.m_it) { - construct_or_replace(construct, dest, boost::move_if_noexcept(*src)); - increment(src); - increment(dest); - construct = false; - } - decrement(pos.m_it); - replace(pos.m_it, static_cast(item)); - } BOOST_CATCH(...) { - if (!construct && !full()) { - decrement(m_first); - ++m_size; - } - BOOST_RETHROW - } - BOOST_CATCH_END - decrement(m_first); - } - if (full()) - m_last = m_first; - else - ++m_size; - return iterator(this, pos.m_it); - } - -public: - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted before the position pos.
- If the circular_buffer is full, the last element will be overwritten. If the - circular_buffer is full and the pos points to end(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position before which the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements before the insertion point (towards the beginning and - excluding pos). It also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(begin(), pos)). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos, param_value_type item) { - return rinsert_impl(pos, item); - } - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted before the position pos.
- If the circular_buffer is full, the last element will be overwritten. If the - circular_buffer is full and the pos points to end(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position before which the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements before the insertion point (towards the beginning and - excluding pos). It also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(begin(), pos)). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos, rvalue_type item) { - return rinsert_impl(pos, boost::move(item)); - } - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The item will be inserted before the position pos.
- If the circular_buffer is full, the last element will be overwritten. If the - circular_buffer is full and the pos points to end(), then the - item will not be inserted. If the capacity is 0, nothing will be inserted. - \param pos An iterator specifying the position before which the item will be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws Whatever T::T() throws. - Whatever T::T(T&&) throws. - Whatever T::operator = (T&&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements before the insertion point (towards the beginning and - excluding pos). It also invalidates iterators pointing to the overwritten element. - \par Complexity - Linear (in std::distance(begin(), pos)). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos) { - value_type temp; - return rinsert(pos, boost::move(temp)); - } - - //! Insert n copies of the item before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end. - \post The number of min[n, (end() - pos) + reserve()] elements will be inserted before the - position pos.
The number of min[end() - pos, max[0, n - reserve()]] elements - will be overwritten at the end of the circular_buffer.
(See Example for the - explanation.) - \param pos An iterator specifying the position where the items will be inserted. - \param n The number of items the to be inserted. - \param item The element whose copies will be inserted. - \throws Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements before the insertion point (towards the beginning and - excluding pos). It also invalidates iterators pointing to the overwritten elements. - \par Complexity - Linear (in min[capacity(), std::distance(begin(), pos) + n]). - \par Example - Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may - look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting 5 elements before the position p:

- rinsert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements - 3 and 4 are overwritten. This is due to the fact the rinsert operation preserves - the capacity. After insertion the internal buffer looks like this:

|1|2|0|0|0|0|
-
For comparison if the capacity would not be preserved the internal buffer would then result in - |1|2|0|0|0|0|0|3|4|. - \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - void rinsert(iterator pos, size_type n, param_value_type item) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - rinsert_n(pos, n, cb_details::item_wrapper(item)); - } - - //! Insert the range [first, last) before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer or its end.
- Valid range [first, last) where first and last meet the - requirements of an InputIterator. - \post Elements from the range - [first, last - max[0, distance(first, last) - (end() - pos) - reserve()]) will be inserted - before the position pos.
The number of min[end() - pos, max[0, - distance(first, last) - reserve()]] elements will be overwritten at the end of the - circular_buffer.
(See Example for the explanation.) - \param pos An iterator specifying the position where the range will be inserted. - \param first The beginning of the range to be inserted. - \param last The end of the range to be inserted. - \throws Whatever T::T(const T&) throws if the InputIterator is not a move iterator. - Whatever T::operator = (const T&) throws if the InputIterator is not a move iterator. - Whatever T::T(T&&) throws if the InputIterator is a move iterator. - Whatever T::operator = (T&&) throws if the InputIterator is a move iterator. - \par Exception Safety - Basic; no-throw if the operations in the Throws section do not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the elements before the insertion point (towards the beginning and - excluding pos). It also invalidates iterators pointing to the overwritten elements. - \par Complexity - Linear (in [std::distance(begin(), pos) + std::distance(first, last)]; in - min[capacity(), std::distance(begin(), pos) + std::distance(first, last)] if the - InputIterator is a - RandomAccessIterator). - \par Example - Consider a circular_buffer with the capacity of 6 and the size of 4. Its internal buffer may - look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting a range of elements before the position p:

- int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

- actually only elements 5, 6, 7 and 8 from the - specified range get inserted and elements 3 and 4 are overwritten. This is due - to the fact the rinsert operation preserves the capacity. After insertion the internal buffer looks like - this:

|1|2|5|6|7|8|

For comparison if the capacity would not be preserved the - internal buffer would then result in |1|2|5|6|7|8|9|3|4|. - \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, \link insert(iterator, param_value_type) - insert(iterator, value_type)\endlink, \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - template - void rinsert(iterator pos, InputIterator first, InputIterator last) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - rinsert(pos, first, last, is_integral()); - } - -// Erase - - //! Remove an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer (but not an - end()). - \post The element at the position pos is removed. - \param pos An iterator pointing at the element to be removed. - \return Iterator to the first element remaining beyond the removed element or end() if no such - element exists. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the erased element and iterators pointing to the elements behind - the erased element (towards the end; except iterators equal to end()). - \par Complexity - Linear (in std::distance(pos, end())). - \sa erase(iterator, iterator), rerase(iterator), - rerase(iterator, iterator), erase_begin(size_type), - erase_end(size_type), clear() - */ - iterator erase(iterator pos) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() - pointer next = pos.m_it; - increment(next); - for (pointer p = pos.m_it; next != m_last; p = next, increment(next)) - replace(p, boost::move_if_noexcept(*next)); - decrement(m_last); - destroy_item(m_last); - --m_size; -#if BOOST_CB_ENABLE_DEBUG - return m_last == pos.m_it ? end() : iterator(this, pos.m_it); -#else - return m_last == pos.m_it ? end() : pos; -#endif - } - - //! Erase the range [first, last). - /*! - \pre Valid range [first, last). - \post The elements from the range [first, last) are removed. (If first == last - nothing is removed.) - \param first The beginning of the range to be removed. - \param last The end of the range to be removed. - \return Iterator to the first element remaining beyond the removed elements or end() if no such - element exists. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the erased elements and iterators pointing to the elements behind - the erased range (towards the end; except iterators equal to end()). - \par Complexity - Linear (in std::distance(first, end())). - \sa erase(iterator), rerase(iterator), rerase(iterator, iterator), - erase_begin(size_type), erase_end(size_type), clear() - */ - iterator erase(iterator first, iterator last) { - BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(first <= last); // check for wrong range - if (first == last) - return first; - pointer p = first.m_it; - while (last.m_it != 0) - replace((first++).m_it, boost::move_if_noexcept(*last++)); - do { - decrement(m_last); - destroy_item(m_last); - --m_size; - } while(m_last != first.m_it); - return m_last == p ? end() : iterator(this, p); - } - - //! Remove an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer (but not an - end()). - \post The element at the position pos is removed. - \param pos An iterator pointing at the element to be removed. - \return Iterator to the first element remaining in front of the removed element or begin() if no - such element exists. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the erased element and iterators pointing to the elements in front of - the erased element (towards the beginning). - \par Complexity - Linear (in std::distance(begin(), pos)). - \note This method is symmetric to the erase(iterator) method and is more effective than - erase(iterator) if the iterator pos is close to the beginning of the - circular_buffer. (See the Complexity.) - \sa erase(iterator), erase(iterator, iterator), - rerase(iterator, iterator), erase_begin(size_type), - erase_end(size_type), clear() - */ - iterator rerase(iterator pos) { - BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() - pointer prev = pos.m_it; - pointer p = prev; - for (decrement(prev); p != m_first; p = prev, decrement(prev)) - replace(p, boost::move_if_noexcept(*prev)); - destroy_item(m_first); - increment(m_first); - --m_size; -#if BOOST_CB_ENABLE_DEBUG - return p == pos.m_it ? begin() : iterator(this, pos.m_it); -#else - return p == pos.m_it ? begin() : pos; -#endif - } - - //! Erase the range [first, last). - /*! - \pre Valid range [first, last). - \post The elements from the range [first, last) are removed. (If first == last - nothing is removed.) - \param first The beginning of the range to be removed. - \param last The end of the range to be removed. - \return Iterator to the first element remaining in front of the removed elements or begin() if no - such element exists. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. - \par Iterator Invalidation - Invalidates iterators pointing to the erased elements and iterators pointing to the elements in front of - the erased range (towards the beginning). - \par Complexity - Linear (in std::distance(begin(), last)). - \note This method is symmetric to the erase(iterator, iterator) method and is more effective than - erase(iterator, iterator) if std::distance(begin(), first) is lower that - std::distance(last, end()). - \sa erase(iterator), erase(iterator, iterator), rerase(iterator), - erase_begin(size_type), erase_end(size_type), clear() - */ - iterator rerase(iterator first, iterator last) { - BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(first <= last); // check for wrong range - if (first == last) - return first; - pointer p = map_pointer(last.m_it); - last.m_it = p; - while (first.m_it != m_first) { - decrement(first.m_it); - decrement(p); - replace(p, boost::move_if_noexcept(*first.m_it)); - } - do { - destroy_item(m_first); - increment(m_first); - --m_size; - } while(m_first != p); - if (m_first == last.m_it) - return begin(); - decrement(last.m_it); - return iterator(this, last.m_it); - } - - //! Remove first n elements (with constant complexity for scalar types). - /*! - \pre n \<= size() - \post The n elements at the beginning of the circular_buffer will be removed. - \param n The number of elements to be removed. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. (I.e. no throw in - case of scalars.) - \par Iterator Invalidation - Invalidates iterators pointing to the first n erased elements. - \par Complexity - Constant (in n) for scalar types; linear for other types. - \note This method has been specially designed for types which do not require an explicit destructruction (e.g. - integer, float or a pointer). For these scalar types a call to a destructor is not required which makes - it possible to implement the "erase from beginning" operation with a constant complexity. For non-sacalar - types the complexity is linear (hence the explicit destruction is needed) and the implementation is - actually equivalent to - \link circular_buffer::rerase(iterator, iterator) rerase(begin(), begin() + n)\endlink. - \sa erase(iterator), erase(iterator, iterator), - rerase(iterator), rerase(iterator, iterator), - erase_end(size_type), clear() - */ - void erase_begin(size_type n) { - BOOST_CB_ASSERT(n <= size()); // check for n greater than size -#if BOOST_CB_ENABLE_DEBUG - erase_begin(n, false_type()); -#else - erase_begin(n, is_scalar()); -#endif - } - - //! Remove last n elements (with constant complexity for scalar types). - /*! - \pre n \<= size() - \post The n elements at the end of the circular_buffer will be removed. - \param n The number of elements to be removed. - \throws Exceptions of move_if_noexcept(T&). - \par Exception Safety - Basic; no-throw if the operation in the Throws section does not throw anything. (I.e. no throw in - case of scalars.) - \par Iterator Invalidation - Invalidates iterators pointing to the last n erased elements. - \par Complexity - Constant (in n) for scalar types; linear for other types. - \note This method has been specially designed for types which do not require an explicit destructruction (e.g. - integer, float or a pointer). For these scalar types a call to a destructor is not required which makes - it possible to implement the "erase from end" operation with a constant complexity. For non-sacalar - types the complexity is linear (hence the explicit destruction is needed) and the implementation is - actually equivalent to - \link circular_buffer::erase(iterator, iterator) erase(end() - n, end())\endlink. - \sa erase(iterator), erase(iterator, iterator), - rerase(iterator), rerase(iterator, iterator), - erase_begin(size_type), clear() - */ - void erase_end(size_type n) { - BOOST_CB_ASSERT(n <= size()); // check for n greater than size -#if BOOST_CB_ENABLE_DEBUG - erase_end(n, false_type()); -#else - erase_end(n, is_scalar()); -#endif - } - - //! Remove all stored elements from the circular_buffer. - /*! - \post size() == 0 - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer (except iterators equal to - end()). - \par Complexity - Constant (in the size of the circular_buffer) for scalar types; linear for other types. - \sa ~circular_buffer(), erase(iterator), erase(iterator, iterator), - rerase(iterator), rerase(iterator, iterator), - erase_begin(size_type), erase_end(size_type) - */ - void clear() BOOST_NOEXCEPT { - destroy_content(); - m_size = 0; - } - -private: -// Helper methods - - /*! INTERNAL ONLY */ - void check_position(size_type index) const { - if (index >= size()) - throw_exception(std::out_of_range("circular_buffer")); - } - - /*! INTERNAL ONLY */ - template - void increment(Pointer& p) const { - if (++p == m_end) - p = m_buff; - } - - /*! INTERNAL ONLY */ - template - void decrement(Pointer& p) const { - if (p == m_buff) - p = m_end; - --p; - } - - /*! INTERNAL ONLY */ - template - Pointer add(Pointer p, difference_type n) const { - return p + (n < (m_end - p) ? n : n - (m_end - m_buff)); - } - - /*! INTERNAL ONLY */ - template - Pointer sub(Pointer p, difference_type n) const { - return p - (n > (p - m_buff) ? n - (m_end - m_buff) : n); - } - - /*! INTERNAL ONLY */ - pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; } - - /*! INTERNAL ONLY */ - const Alloc& alloc() const { - return base::get(); - } - - /*! INTERNAL ONLY */ - Alloc& alloc() { - return base::get(); - } - - /*! INTERNAL ONLY */ - pointer allocate(size_type n) { - if (n > max_size()) - throw_exception(std::length_error("circular_buffer")); -#if BOOST_CB_ENABLE_DEBUG - pointer p = (n == 0) ? 0 : alloc().allocate(n); - cb_details::do_fill_uninitialized_memory(p, sizeof(value_type) * n); - return p; -#else - return (n == 0) ? 0 : alloc().allocate(n); -#endif - } - - /*! INTERNAL ONLY */ - void deallocate(pointer p, size_type n) { - if (p != 0) - alloc().deallocate(p, n); - } - - /*! INTERNAL ONLY */ - bool is_uninitialized(const_pointer p) const BOOST_NOEXCEPT { - return (m_first < m_last) - ? (p >= m_last || p < m_first) - : (p >= m_last && p < m_first); - } - - /*! INTERNAL ONLY */ - void replace(pointer pos, param_value_type item) { - *pos = item; -#if BOOST_CB_ENABLE_DEBUG - invalidate_iterators(iterator(this, pos)); -#endif - } - - /*! INTERNAL ONLY */ - void replace(pointer pos, rvalue_type item) { - *pos = boost::move(item); -#if BOOST_CB_ENABLE_DEBUG - invalidate_iterators(iterator(this, pos)); -#endif - } - - /*! INTERNAL ONLY */ - void construct_or_replace(bool construct, pointer pos, param_value_type item) { - if (construct) - boost::allocator_construct(alloc(), boost::to_address(pos), item); - else - replace(pos, item); - } - - /*! INTERNAL ONLY */ - void construct_or_replace(bool construct, pointer pos, rvalue_type item) { - if (construct) - boost::allocator_construct(alloc(), boost::to_address(pos), boost::move(item)); - else - replace(pos, boost::move(item)); - } - - /*! INTERNAL ONLY */ - void destroy_item(pointer p) { - boost::allocator_destroy(alloc(), boost::to_address(p)); -#if BOOST_CB_ENABLE_DEBUG - invalidate_iterators(iterator(this, p)); - cb_details::do_fill_uninitialized_memory(p, sizeof(value_type)); -#endif - } - - /*! INTERNAL ONLY */ - void destroy_if_constructed(pointer pos) { - if (is_uninitialized(pos)) - destroy_item(pos); - } - - /*! INTERNAL ONLY */ - void destroy_content() { -#if BOOST_CB_ENABLE_DEBUG - destroy_content(false_type()); -#else - destroy_content(is_scalar()); -#endif - } - - /*! INTERNAL ONLY */ - void destroy_content(const true_type&) { - m_first = add(m_first, size()); - } - - /*! INTERNAL ONLY */ - void destroy_content(const false_type&) { - for (size_type ii = 0; ii < size(); ++ii, increment(m_first)) - destroy_item(m_first); - } - - /*! INTERNAL ONLY */ - void destroy() BOOST_NOEXCEPT { - destroy_content(); - deallocate(m_buff, capacity()); -#if BOOST_CB_ENABLE_DEBUG - m_buff = 0; - m_first = 0; - m_last = 0; - m_end = 0; -#endif - } - - /*! INTERNAL ONLY */ - void initialize_buffer(capacity_type buffer_capacity) { - m_buff = allocate(buffer_capacity); - m_end = m_buff + buffer_capacity; - } - - /*! INTERNAL ONLY */ - void initialize_buffer(capacity_type buffer_capacity, param_value_type item) { - initialize_buffer(buffer_capacity); - BOOST_TRY { - cb_details::uninitialized_fill_n_with_alloc(m_buff, size(), item, alloc()); - } BOOST_CATCH(...) { - deallocate(m_buff, size()); - BOOST_RETHROW - } - BOOST_CATCH_END - } - - /*! INTERNAL ONLY */ - template - void initialize(IntegralType n, IntegralType item, const true_type&) { - m_size = static_cast(n); - initialize_buffer(size(), item); - m_first = m_last = m_buff; - } - - /*! INTERNAL ONLY */ - template - void initialize(Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - initialize(first, last, std::iterator_traits::iterator_category()); -#else - initialize(first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void initialize(InputIterator first, InputIterator last, const std::input_iterator_tag&) { - BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors - // for containers - std::deque tmp(first, last, alloc()); - size_type distance = tmp.size(); - initialize(distance, boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), distance); - } - - /*! INTERNAL ONLY */ - template - void initialize(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - size_type distance = std::distance(first, last); - initialize(distance, first, last, distance); - } - - /*! INTERNAL ONLY */ - template - void initialize(capacity_type buffer_capacity, IntegralType n, IntegralType item, const true_type&) { - BOOST_CB_ASSERT(buffer_capacity >= static_cast(n)); // check for capacity lower than n - m_size = static_cast(n); - initialize_buffer(buffer_capacity, item); - m_first = m_buff; - m_last = buffer_capacity == size() ? m_buff : m_buff + size(); - } - - /*! INTERNAL ONLY */ - template - void initialize(capacity_type buffer_capacity, Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - initialize(buffer_capacity, first, last, std::iterator_traits::iterator_category()); -#else - initialize(buffer_capacity, first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void initialize(capacity_type buffer_capacity, - InputIterator first, - InputIterator last, - const std::input_iterator_tag&) { - initialize_buffer(buffer_capacity); - m_first = m_last = m_buff; - m_size = 0; - if (buffer_capacity == 0) - return; - while (first != last && !full()) { - boost::allocator_construct(alloc(), boost::to_address(m_last), *first++); - increment(m_last); - ++m_size; - } - while (first != last) { - replace(m_last, *first++); - increment(m_last); - m_first = m_last; - } - } - - /*! INTERNAL ONLY */ - template - void initialize(capacity_type buffer_capacity, - ForwardIterator first, - ForwardIterator last, - const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - initialize(buffer_capacity, first, last, std::distance(first, last)); - } - - /*! INTERNAL ONLY */ - template - void initialize(capacity_type buffer_capacity, - ForwardIterator first, - ForwardIterator last, - size_type distance) { - initialize_buffer(buffer_capacity); - m_first = m_buff; - if (distance > buffer_capacity) { - std::advance(first, distance - buffer_capacity); - m_size = buffer_capacity; - } else { - m_size = distance; - } - BOOST_TRY { - m_last = cb_details::uninitialized_copy(first, last, m_buff, alloc()); - } BOOST_CATCH(...) { - deallocate(m_buff, buffer_capacity); - BOOST_RETHROW - } - BOOST_CATCH_END - if (m_last == m_end) - m_last = m_buff; - } - - /*! INTERNAL ONLY */ - void reset(pointer buff, pointer last, capacity_type new_capacity) { - destroy(); - m_size = last - buff; - m_first = m_buff = buff; - m_end = m_buff + new_capacity; - m_last = last == m_end ? m_buff : last; - } - - /*! INTERNAL ONLY */ - void swap_allocator(circular_buffer&, const true_type&) { - // Swap is not needed because allocators have no state. - } - - /*! INTERNAL ONLY */ - void swap_allocator(circular_buffer& cb, const false_type&) { - adl_move_swap(alloc(), cb.alloc()); - } - - /*! INTERNAL ONLY */ - template - void assign(IntegralType n, IntegralType item, const true_type&) { - assign(static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void assign(Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - assign(first, last, std::iterator_traits::iterator_category()); -#else - assign(first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void assign(InputIterator first, InputIterator last, const std::input_iterator_tag&) { - BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors - // for containers - std::deque tmp(first, last, alloc()); - size_type distance = tmp.size(); - assign_n(distance, distance, - cb_details::make_assign_range - (boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), alloc())); - } - - /*! INTERNAL ONLY */ - template - void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - size_type distance = std::distance(first, last); - assign_n(distance, distance, cb_details::make_assign_range(first, last, alloc())); - } - - /*! INTERNAL ONLY */ - template - void assign(capacity_type new_capacity, IntegralType n, IntegralType item, const true_type&) { - assign(new_capacity, static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void assign(capacity_type new_capacity, Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - assign(new_capacity, first, last, std::iterator_traits::iterator_category()); -#else - assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void assign(capacity_type new_capacity, InputIterator first, InputIterator last, const std::input_iterator_tag&) { - if (new_capacity == capacity()) { - clear(); - insert(begin(), first, last); - } else { - circular_buffer tmp(new_capacity, first, last, alloc()); - tmp.swap(*this); - } - } - - /*! INTERNAL ONLY */ - template - void assign(capacity_type new_capacity, ForwardIterator first, ForwardIterator last, - const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - size_type distance = std::distance(first, last); - if (distance > new_capacity) { - std::advance(first, distance - new_capacity); - distance = new_capacity; - } - assign_n(new_capacity, distance, - cb_details::make_assign_range(first, last, alloc())); - } - - /*! INTERNAL ONLY */ - template - void assign_n(capacity_type new_capacity, size_type n, const Functor& fnc) { - if (new_capacity == capacity()) { - destroy_content(); - BOOST_TRY { - fnc(m_buff); - } BOOST_CATCH(...) { - m_size = 0; - BOOST_RETHROW - } - BOOST_CATCH_END - } else { - pointer buff = allocate(new_capacity); - BOOST_TRY { - fnc(buff); - } BOOST_CATCH(...) { - deallocate(buff, new_capacity); - BOOST_RETHROW - } - BOOST_CATCH_END - destroy(); - m_buff = buff; - m_end = m_buff + new_capacity; - } - m_size = n; - m_first = m_buff; - m_last = add(m_buff, size()); - } - - /*! INTERNAL ONLY */ - template - iterator insert_item(const iterator& pos, ValT item) { - pointer p = pos.m_it; - if (p == 0) { - construct_or_replace(!full(), m_last, static_cast(item)); - p = m_last; - } else { - pointer src = m_last; - pointer dest = m_last; - bool construct = !full(); - BOOST_TRY { - while (src != p) { - decrement(src); - construct_or_replace(construct, dest, boost::move_if_noexcept(*src)); - decrement(dest); - construct = false; - } - replace(p, static_cast(item)); - } BOOST_CATCH(...) { - if (!construct && !full()) { - increment(m_last); - ++m_size; - } - BOOST_RETHROW - } - BOOST_CATCH_END - } - increment(m_last); - if (full()) - m_first = m_last; - else - ++m_size; - return iterator(this, p); - } - - /*! INTERNAL ONLY */ - template - void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { - insert(pos, static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - insert(pos, first, last, std::iterator_traits::iterator_category()); -#else - insert(pos, first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void insert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) { - if (!full() || pos != begin()) { - for (;first != last; ++pos) - pos = insert(pos, *first++); - } - } - - /*! INTERNAL ONLY */ - template - void insert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - size_type n = std::distance(first, last); - if (n == 0) - return; - size_type copy = capacity() - (end() - pos); - if (copy == 0) - return; - if (n > copy) { - std::advance(first, n - copy); - n = copy; - } - insert_n(pos, n, cb_details::iterator_wrapper(first)); - } - - /*! INTERNAL ONLY */ - template - void insert_n(const iterator& pos, size_type n, const Wrapper& wrapper) { - size_type construct = reserve(); - if (construct > n) - construct = n; - if (pos.m_it == 0) { - size_type ii = 0; - pointer p = m_last; - BOOST_TRY { - for (; ii < construct; ++ii, increment(p)) - boost::allocator_construct(alloc(), boost::to_address(p), *wrapper()); - for (;ii < n; ++ii, increment(p)) - replace(p, *wrapper()); - } BOOST_CATCH(...) { - size_type constructed = (std::min)(ii, construct); - m_last = add(m_last, constructed); - m_size += constructed; - BOOST_RETHROW - } - BOOST_CATCH_END - } else { - pointer src = m_last; - pointer dest = add(m_last, n - 1); - pointer p = pos.m_it; - size_type ii = 0; - BOOST_TRY { - while (src != pos.m_it) { - decrement(src); - construct_or_replace(is_uninitialized(dest), dest, *src); - decrement(dest); - } - for (; ii < n; ++ii, increment(p)) - construct_or_replace(is_uninitialized(p), p, *wrapper()); - } BOOST_CATCH(...) { - for (p = add(m_last, n - 1); p != dest; decrement(p)) - destroy_if_constructed(p); - for (n = 0, p = pos.m_it; n < ii; ++n, increment(p)) - destroy_if_constructed(p); - BOOST_RETHROW - } - BOOST_CATCH_END - } - m_last = add(m_last, n); - m_first = add(m_first, n - construct); - m_size += construct; - } - - /*! INTERNAL ONLY */ - template - void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { - rinsert(pos, static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - rinsert(pos, first, last, std::iterator_traits::iterator_category()); -#else - rinsert(pos, first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - void rinsert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) { - if (!full() || pos.m_it != 0) { - for (;first != last; ++pos) { - pos = rinsert(pos, *first++); - if (pos.m_it == 0) - break; - } - } - } - - /*! INTERNAL ONLY */ - template - void rinsert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper(first)); - } - - /*! INTERNAL ONLY */ - template - void rinsert_n(const iterator& pos, size_type n, const Wrapper& wrapper) { - if (n == 0) - return; - iterator b = begin(); - size_type copy = capacity() - (pos - b); - if (copy == 0) - return; - if (n > copy) - n = copy; - size_type construct = reserve(); - if (construct > n) - construct = n; - if (pos == b) { - pointer p = sub(m_first, n); - size_type ii = n; - BOOST_TRY { - for (;ii > construct; --ii, increment(p)) - replace(p, *wrapper()); - for (; ii > 0; --ii, increment(p)) - boost::allocator_construct(alloc(), boost::to_address(p), *wrapper()); - } BOOST_CATCH(...) { - size_type constructed = ii < construct ? construct - ii : 0; - m_last = add(m_last, constructed); - m_size += constructed; - BOOST_RETHROW - } - BOOST_CATCH_END - } else { - pointer src = m_first; - pointer dest = sub(m_first, n); - pointer p = map_pointer(pos.m_it); - BOOST_TRY { - while (src != p) { - construct_or_replace(is_uninitialized(dest), dest, *src); - increment(src); - increment(dest); - } - for (size_type ii = 0; ii < n; ++ii, increment(dest)) - construct_or_replace(is_uninitialized(dest), dest, *wrapper()); - } BOOST_CATCH(...) { - for (src = sub(m_first, n); src != dest; increment(src)) - destroy_if_constructed(src); - BOOST_RETHROW - } - BOOST_CATCH_END - } - m_first = sub(m_first, n); - m_last = sub(m_last, n - construct); - m_size += construct; - } - - /*! INTERNAL ONLY */ - void erase_begin(size_type n, const true_type&) { - m_first = add(m_first, n); - m_size -= n; - } - - /*! INTERNAL ONLY */ - void erase_begin(size_type n, const false_type&) { - iterator b = begin(); - rerase(b, b + n); - } - - /*! INTERNAL ONLY */ - void erase_end(size_type n, const true_type&) { - m_last = sub(m_last, n); - m_size -= n; - } - - /*! INTERNAL ONLY */ - void erase_end(size_type n, const false_type&) { - iterator e = end(); - erase(e - n, e); - } -}; - -// Non-member functions - -//! Compare two circular_buffers element-by-element to determine if they are equal. -/*! - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return lhs.\link circular_buffer::size() size()\endlink == rhs.\link circular_buffer::size() size()\endlink - && std::equal(lhs.\link circular_buffer::begin() - begin()\endlink, lhs.\link circular_buffer::end() end()\endlink, - rhs.\link circular_buffer::begin() begin()\endlink) - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. -*/ -template -inline bool operator == (const circular_buffer& lhs, const circular_buffer& rhs) { - return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -/*! - \brief Compare two circular_buffers element-by-element to determine if the left one is lesser than the - right one. - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return - std::lexicographical_compare(lhs.\link circular_buffer::begin() begin()\endlink, - lhs.\link circular_buffer::end() end()\endlink, rhs.\link circular_buffer::begin() begin()\endlink, - rhs.\link circular_buffer::end() end()\endlink) - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. -*/ -template -inline bool operator < (const circular_buffer& lhs, const circular_buffer& rhs) { - return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); -} - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) - -//! Compare two circular_buffers element-by-element to determine if they are non-equal. -/*! - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return !(lhs == rhs) - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. - \sa operator==(const circular_buffer&, const circular_buffer&) -*/ -template -inline bool operator != (const circular_buffer& lhs, const circular_buffer& rhs) { - return !(lhs == rhs); -} - -/*! - \brief Compare two circular_buffers element-by-element to determine if the left one is greater than - the right one. - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return rhs \< lhs - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. - \sa operator<(const circular_buffer&, const circular_buffer&) -*/ -template -inline bool operator > (const circular_buffer& lhs, const circular_buffer& rhs) { - return rhs < lhs; -} - -/*! - \brief Compare two circular_buffers element-by-element to determine if the left one is lesser or equal - to the right one. - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return !(rhs \< lhs) - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. - \sa operator<(const circular_buffer&, const circular_buffer&) -*/ -template -inline bool operator <= (const circular_buffer& lhs, const circular_buffer& rhs) { - return !(rhs < lhs); -} - -/*! - \brief Compare two circular_buffers element-by-element to determine if the left one is greater or - equal to the right one. - \param lhs The circular_buffer to compare. - \param rhs The circular_buffer to compare. - \return !(lhs < rhs) - \throws Nothing. - \par Complexity - Linear (in the size of the circular_buffers). - \par Iterator Invalidation - Does not invalidate any iterators. - \sa operator<(const circular_buffer&, const circular_buffer&) -*/ -template -inline bool operator >= (const circular_buffer& lhs, const circular_buffer& rhs) { - return !(lhs < rhs); -} - -//! Swap the contents of two circular_buffers. -/*! - \post lhs contains elements of rhs and vice versa. - \param lhs The circular_buffer whose content will be swapped with rhs. - \param rhs The circular_buffer whose content will be swapped with lhs. - \throws Nothing. - \par Complexity - Constant (in the size of the circular_buffers). - \par Iterator Invalidation - Invalidates all iterators of both circular_buffers. (On the other hand the iterators still - point to the same elements but within another container. If you want to rely on this feature you have to - turn the Debug Support off otherwise an assertion will report an error if such - invalidated iterator is used.) - \sa \link circular_buffer::swap(circular_buffer&) swap(circular_buffer&)\endlink -*/ -template -inline void swap(circular_buffer& lhs, circular_buffer& rhs) BOOST_NOEXCEPT { - lhs.swap(rhs); -} - -#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC) - -} // namespace boost - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP) diff --git a/boost/circular_buffer/debug.hpp b/boost/circular_buffer/debug.hpp deleted file mode 100644 index b6ab0fe..0000000 --- a/boost/circular_buffer/debug.hpp +++ /dev/null @@ -1,248 +0,0 @@ -// Debug support for the circular buffer library. - -// Copyright (c) 2003-2008 Jan Gaspar - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) -#define BOOST_CIRCULAR_BUFFER_DEBUG_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#if BOOST_CB_ENABLE_DEBUG -#include - -#if defined(BOOST_NO_STDC_NAMESPACE) -namespace std { - using ::memset; -} -#endif - -#endif // BOOST_CB_ENABLE_DEBUG -namespace boost { - -namespace cb_details { - -#if BOOST_CB_ENABLE_DEBUG - -// The value the uninitialized memory is filled with. -const int UNINITIALIZED = 0xcc; - -template -inline void do_fill_uninitialized_memory(T* data, std::size_t size_in_bytes) BOOST_NOEXCEPT { - std::memset(static_cast(data), UNINITIALIZED, size_in_bytes); -} - -template -inline void do_fill_uninitialized_memory(T& /*data*/, std::size_t /*size_in_bytes*/) BOOST_NOEXCEPT { - // Do nothing -} - - -class debug_iterator_registry; - -/*! - \class debug_iterator_base - \brief Registers/unregisters iterators into the registry of valid iterators. - - This class is intended to be a base class of an iterator. -*/ -class debug_iterator_base { - -private: -// Members - - //! Iterator registry. - mutable const debug_iterator_registry* m_registry; - - //! Next iterator in the iterator chain. - mutable const debug_iterator_base* m_next; - -public: -// Construction/destruction - - //! Default constructor. - debug_iterator_base(); - - //! Constructor taking the iterator registry as a parameter. - debug_iterator_base(const debug_iterator_registry* registry); - - //! Copy constructor. - debug_iterator_base(const debug_iterator_base& rhs); - - //! Destructor. - ~debug_iterator_base(); - -// Methods - - //! Assign operator. - debug_iterator_base& operator = (const debug_iterator_base& rhs); - - //! Is the iterator valid? - bool is_valid(const debug_iterator_registry* registry) const; - - //! Invalidate the iterator. - /*! - \note The method is const in order to invalidate const iterators, too. - */ - void invalidate() const; - - //! Return the next iterator in the iterator chain. - const debug_iterator_base* next() const; - - //! Set the next iterator in the iterator chain. - /*! - \note The method is const in order to set a next iterator to a const iterator, too. - */ - void set_next(const debug_iterator_base* it) const; - -private: -// Helpers - - //! Register self as a valid iterator. - void register_self(); - - //! Unregister self from valid iterators. - void unregister_self(); -}; - -/*! - \class debug_iterator_registry - \brief Registry of valid iterators. - - This class is intended to be a base class of a container. -*/ -class debug_iterator_registry { - - //! Pointer to the chain of valid iterators. - mutable const debug_iterator_base* m_iterators; - -public: -// Methods - - //! Default constructor. - debug_iterator_registry() : m_iterators(0) {} - - //! Register an iterator into the list of valid iterators. - /*! - \note The method is const in order to register iterators into const containers, too. - */ - void register_iterator(const debug_iterator_base* it) const { - it->set_next(m_iterators); - m_iterators = it; - } - - //! Unregister an iterator from the list of valid iterators. - /*! - \note The method is const in order to unregister iterators from const containers, too. - */ - void unregister_iterator(const debug_iterator_base* it) const { - const debug_iterator_base* previous = 0; - for (const debug_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()) {} - remove(it, previous); - } - - //! Invalidate every iterator pointing to the same element as the iterator passed as a parameter. - template - void invalidate_iterators(const Iterator& it) { - const debug_iterator_base* previous = 0; - for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { - if (((Iterator*)p)->m_it == it.m_it) { - p->invalidate(); - remove(p, previous); - continue; - } - previous = p; - } - } - - //! Invalidate all iterators except an iterator poining to the same element as the iterator passed as a parameter. - template - void invalidate_iterators_except(const Iterator& it) { - const debug_iterator_base* previous = 0; - for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) { - if (((Iterator*)p)->m_it != it.m_it) { - p->invalidate(); - remove(p, previous); - continue; - } - previous = p; - } - } - - //! Invalidate all iterators. - void invalidate_all_iterators() { - for (const debug_iterator_base* p = m_iterators; p != 0; p = p->next()) - p->invalidate(); - m_iterators = 0; - } - -private: -// Helpers - - //! Remove the current iterator from the iterator chain. - void remove(const debug_iterator_base* current, - const debug_iterator_base* previous) const { - if (previous == 0) - m_iterators = m_iterators->next(); - else - previous->set_next(current->next()); - } -}; - -// Implementation of the debug_iterator_base methods. - -inline debug_iterator_base::debug_iterator_base() : m_registry(0), m_next(0) {} - -inline debug_iterator_base::debug_iterator_base(const debug_iterator_registry* registry) -: m_registry(registry), m_next(0) { - register_self(); -} - -inline debug_iterator_base::debug_iterator_base(const debug_iterator_base& rhs) -: m_registry(rhs.m_registry), m_next(0) { - register_self(); -} - -inline debug_iterator_base::~debug_iterator_base() { unregister_self(); } - -inline debug_iterator_base& debug_iterator_base::operator = (const debug_iterator_base& rhs) { - if (m_registry == rhs.m_registry) - return *this; - unregister_self(); - m_registry = rhs.m_registry; - register_self(); - return *this; -} - -inline bool debug_iterator_base::is_valid(const debug_iterator_registry* registry) const { - return m_registry == registry; -} - -inline void debug_iterator_base::invalidate() const { m_registry = 0; } - -inline const debug_iterator_base* debug_iterator_base::next() const { return m_next; } - -inline void debug_iterator_base::set_next(const debug_iterator_base* it) const { m_next = it; } - -inline void debug_iterator_base::register_self() { - if (m_registry != 0) - m_registry->register_iterator(this); -} - -inline void debug_iterator_base::unregister_self() { - if (m_registry != 0) - m_registry->unregister_iterator(this); -} - -#endif // #if BOOST_CB_ENABLE_DEBUG - -} // namespace cb_details - -} // namespace boost - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DEBUG_HPP) diff --git a/boost/circular_buffer/details.hpp b/boost/circular_buffer/details.hpp deleted file mode 100644 index d6d48f3..0000000 --- a/boost/circular_buffer/details.hpp +++ /dev/null @@ -1,491 +0,0 @@ -// Helper classes and functions for the circular buffer. - -// Copyright (c) 2003-2008 Jan Gaspar - -// Copyright 2014,2018 Glen Joseph Fernandes -// (glenjofe@gmail.com) - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP) -#define BOOST_CIRCULAR_BUFFER_DETAILS_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include - -// Silence MS /W4 warnings like C4913: -// "user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used" -// This might happen when previously including some boost headers that overload the coma operator. -#if defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable:4913) -#endif - -namespace boost { - -namespace cb_details { - -template struct nonconst_traits; - -template -void uninitialized_fill_n_with_alloc( - ForwardIterator first, Diff n, const T& item, Alloc& alloc); - -template -ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a); - -template -ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a); - -/*! - \struct const_traits - \brief Defines the data types for a const iterator. -*/ -template -struct const_traits { - // Basic types - typedef typename Alloc::value_type value_type; - typedef typename boost::allocator_const_pointer::type pointer; - typedef const value_type& reference; - typedef typename boost::allocator_size_type::type size_type; - typedef typename boost::allocator_difference_type::type difference_type; - - // Non-const traits - typedef nonconst_traits nonconst_self; -}; - -/*! - \struct nonconst_traits - \brief Defines the data types for a non-const iterator. -*/ -template -struct nonconst_traits { - // Basic types - typedef typename Alloc::value_type value_type; - typedef typename boost::allocator_pointer::type pointer; - typedef value_type& reference; - typedef typename boost::allocator_size_type::type size_type; - typedef typename boost::allocator_difference_type::type difference_type; - - // Non-const traits - typedef nonconst_traits nonconst_self; -}; - -/*! - \struct iterator_wrapper - \brief Helper iterator dereference wrapper. -*/ -template -struct iterator_wrapper { - mutable Iterator m_it; - explicit iterator_wrapper(Iterator it) : m_it(it) {} - Iterator operator () () const { return m_it++; } -private: - iterator_wrapper& operator = (const iterator_wrapper&); // do not generate -}; - -/*! - \struct item_wrapper - \brief Helper item dereference wrapper. -*/ -template -struct item_wrapper { - Value m_item; - explicit item_wrapper(Value item) : m_item(item) {} - Pointer operator () () const { return &m_item; } -private: - item_wrapper& operator = (const item_wrapper&); // do not generate -}; - -/*! - \struct assign_n - \brief Helper functor for assigning n items. -*/ -template -struct assign_n { - typedef typename boost::allocator_size_type::type size_type; - size_type m_n; - Value m_item; - Alloc& m_alloc; - assign_n(size_type n, Value item, Alloc& alloc) : m_n(n), m_item(item), m_alloc(alloc) {} - template - void operator () (Pointer p) const { - uninitialized_fill_n_with_alloc(p, m_n, m_item, m_alloc); - } -private: - assign_n& operator = (const assign_n&); // do not generate -}; - -/*! - \struct assign_range - \brief Helper functor for assigning range of items. -*/ -template -struct assign_range { - Iterator m_first; - Iterator m_last; - Alloc& m_alloc; - - assign_range(const Iterator& first, const Iterator& last, Alloc& alloc) - : m_first(first), m_last(last), m_alloc(alloc) {} - - template - void operator () (Pointer p) const { - boost::cb_details::uninitialized_copy(m_first, m_last, p, m_alloc); - } -}; - -template -inline assign_range make_assign_range(const Iterator& first, const Iterator& last, Alloc& a) { - return assign_range(first, last, a); -} - -/*! - \class capacity_control - \brief Capacity controller of the space optimized circular buffer. -*/ -template -class capacity_control { - - //! The capacity of the space-optimized circular buffer. - Size m_capacity; - - //! The lowest guaranteed or minimum capacity of the adapted space-optimized circular buffer. - Size m_min_capacity; - -public: - - //! Constructor. - capacity_control(Size buffer_capacity, Size min_buffer_capacity = 0) - : m_capacity(buffer_capacity), m_min_capacity(min_buffer_capacity) - { // Check for capacity lower than min_capacity. - BOOST_CB_ASSERT(buffer_capacity >= min_buffer_capacity); - } - - // Default copy constructor. - - // Default assign operator. - - //! Get the capacity of the space optimized circular buffer. - Size capacity() const { return m_capacity; } - - //! Get the minimal capacity of the space optimized circular buffer. - Size min_capacity() const { return m_min_capacity; } - - //! Size operator - returns the capacity of the space optimized circular buffer. - operator Size() const { return m_capacity; } -}; - -/*! - \struct iterator - \brief Random access iterator for the circular buffer. - \param Buff The type of the underlying circular buffer. - \param Traits Basic iterator types. - \note This iterator is not circular. It was designed - for iterating from begin() to end() of the circular buffer. -*/ -template -struct iterator -#if BOOST_CB_ENABLE_DEBUG - : public debug_iterator_base -#endif // #if BOOST_CB_ENABLE_DEBUG -{ -// Helper types - - //! Non-const iterator. - typedef iterator nonconst_self; - -// Basic types - typedef std::random_access_iterator_tag iterator_category; - - //! The type of the elements stored in the circular buffer. - typedef typename Traits::value_type value_type; - - //! Pointer to the element. - typedef typename Traits::pointer pointer; - - //! Reference to the element. - typedef typename Traits::reference reference; - - //! Size type. - typedef typename Traits::size_type size_type; - - //! Difference type. - typedef typename Traits::difference_type difference_type; - -// Member variables - - //! The circular buffer where the iterator points to. - const Buff* m_buff; - - //! An internal iterator. - pointer m_it; - -// Construction & assignment - - // Default copy constructor. - - //! Default constructor. - iterator() : m_buff(0), m_it(0) {} - -#if BOOST_CB_ENABLE_DEBUG - - //! Copy constructor (used for converting from a non-const to a const iterator). - iterator(const nonconst_self& it) : debug_iterator_base(it), m_buff(it.m_buff), m_it(it.m_it) {} - - //! Internal constructor. - /*! - \note This constructor is not intended to be used directly by the user. - */ - iterator(const Buff* cb, const pointer p) : debug_iterator_base(cb), m_buff(cb), m_it(p) {} - -#else - - iterator(const nonconst_self& it) : m_buff(it.m_buff), m_it(it.m_it) {} - - iterator(const Buff* cb, const pointer p) : m_buff(cb), m_it(p) {} - -#endif // #if BOOST_CB_ENABLE_DEBUG - - //! Assign operator. -#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) - iterator& operator=(const iterator&) = default; -#else - iterator& operator=(const iterator& it) { - if (this == &it) - return *this; -#if BOOST_CB_ENABLE_DEBUG - debug_iterator_base::operator =(it); -#endif // #if BOOST_CB_ENABLE_DEBUG - m_buff = it.m_buff; - m_it = it.m_it; - return *this; - } -#endif - -// Random access iterator methods - - //! Dereferencing operator. - reference operator * () const { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() - return *m_it; - } - - //! Dereferencing operator. - pointer operator -> () const { return &(operator*()); } - - //! Difference operator. - template - difference_type operator - (const iterator& it) const { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator - return linearize_pointer(*this) - linearize_pointer(it); - } - - //! Increment operator (prefix). - iterator& operator ++ () { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(m_it != 0); // check for iterator pointing to end() - m_buff->increment(m_it); - if (m_it == m_buff->m_last) - m_it = 0; - return *this; - } - - //! Increment operator (postfix). - iterator operator ++ (int) { - iterator tmp = *this; - ++*this; - return tmp; - } - - //! Decrement operator (prefix). - iterator& operator -- () { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(m_it != m_buff->m_first); // check for iterator pointing to begin() - if (m_it == 0) - m_it = m_buff->m_last; - m_buff->decrement(m_it); - return *this; - } - - //! Decrement operator (postfix). - iterator operator -- (int) { - iterator tmp = *this; - --*this; - return tmp; - } - - //! Iterator addition. - iterator& operator += (difference_type n) { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - if (n > 0) { - BOOST_CB_ASSERT(m_buff->end() - *this >= n); // check for too large n - m_it = m_buff->add(m_it, n); - if (m_it == m_buff->m_last) - m_it = 0; - } else if (n < 0) { - *this -= -n; - } - return *this; - } - - //! Iterator addition. - iterator operator + (difference_type n) const { return iterator(*this) += n; } - - //! Iterator subtraction. - iterator& operator -= (difference_type n) { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - if (n > 0) { - BOOST_CB_ASSERT(*this - m_buff->begin() >= n); // check for too large n - m_it = m_buff->sub(m_it == 0 ? m_buff->m_last : m_it, n); - } else if (n < 0) { - *this += -n; - } - return *this; - } - - //! Iterator subtraction. - iterator operator - (difference_type n) const { return iterator(*this) -= n; } - - //! Element access operator. - reference operator [] (difference_type n) const { return *(*this + n); } - -// Equality & comparison - - //! Equality. - template - bool operator == (const iterator& it) const { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator - return m_it == it.m_it; - } - - //! Inequality. - template - bool operator != (const iterator& it) const { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator - return m_it != it.m_it; - } - - //! Less. - template - bool operator < (const iterator& it) const { - BOOST_CB_ASSERT(is_valid(m_buff)); // check for uninitialized or invalidated iterator - BOOST_CB_ASSERT(it.is_valid(m_buff)); // check for uninitialized or invalidated iterator - return linearize_pointer(*this) < linearize_pointer(it); - } - - //! Greater. - template - bool operator > (const iterator& it) const { return it < *this; } - - //! Less or equal. - template - bool operator <= (const iterator& it) const { return !(it < *this); } - - //! Greater or equal. - template - bool operator >= (const iterator& it) const { return !(*this < it); } - -// Helpers - - //! Get a pointer which would point to the same element as the iterator in case the circular buffer is linearized. - template - typename Traits0::pointer linearize_pointer(const iterator& it) const { - return it.m_it == 0 ? m_buff->m_buff + m_buff->size() : - (it.m_it < m_buff->m_first ? it.m_it + (m_buff->m_end - m_buff->m_first) - : m_buff->m_buff + (it.m_it - m_buff->m_first)); - } -}; - -//! Iterator addition. -template -inline iterator -operator + (typename Traits::difference_type n, const iterator& it) { - return it + n; -} - -/*! - \fn ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest) - \brief Equivalent of std::uninitialized_copy but with explicit specification of value type. -*/ -template -inline ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) { - ForwardIterator next = dest; - BOOST_TRY { - for (; first != last; ++first, ++dest) - boost::allocator_construct(a, boost::to_address(dest), *first); - } BOOST_CATCH(...) { - for (; next != dest; ++next) - boost::allocator_destroy(a, boost::to_address(next)); - BOOST_RETHROW - } - BOOST_CATCH_END - return dest; -} - -template -ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a, - true_type) { - for (; first != last; ++first, ++dest) - boost::allocator_construct(a, boost::to_address(dest), boost::move(*first)); - return dest; -} - -template -ForwardIterator uninitialized_move_if_noexcept_impl(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a, - false_type) { - return uninitialized_copy(first, last, dest, a); -} - -/*! - \fn ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest) - \brief Equivalent of std::uninitialized_copy but with explicit specification of value type and moves elements if they have noexcept move constructors. -*/ -template -ForwardIterator uninitialized_move_if_noexcept(InputIterator first, InputIterator last, ForwardIterator dest, Alloc& a) { - typedef typename boost::is_nothrow_move_constructible::type tag_t; - return uninitialized_move_if_noexcept_impl(first, last, dest, a, tag_t()); -} - -/*! - \fn void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) - \brief Equivalent of std::uninitialized_fill_n with allocator. -*/ -template -inline void uninitialized_fill_n_with_alloc(ForwardIterator first, Diff n, const T& item, Alloc& alloc) { - ForwardIterator next = first; - BOOST_TRY { - for (; n > 0; ++first, --n) - boost::allocator_construct(alloc, boost::to_address(first), item); - } BOOST_CATCH(...) { - for (; next != first; ++next) - boost::allocator_destroy(alloc, boost::to_address(next)); - BOOST_RETHROW - } - BOOST_CATCH_END -} - -} // namespace cb_details - -} // namespace boost - -#if defined(_MSC_VER) -# pragma warning(pop) -#endif - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_DETAILS_HPP) diff --git a/boost/circular_buffer/space_optimized.hpp b/boost/circular_buffer/space_optimized.hpp deleted file mode 100644 index 21681fd..0000000 --- a/boost/circular_buffer/space_optimized.hpp +++ /dev/null @@ -1,1713 +0,0 @@ -// Implementation of the circular buffer adaptor. - -// Copyright (c) 2003-2008 Jan Gaspar -// Copyright (c) 2013 Paul A. Bristow // Doxygen comments changed for new version of documentation. -// Copyright (c) 2013 Antony Polukhin // Move semantics implementation. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#if !defined(BOOST_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP) -#define BOOST_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#include -#include - -namespace boost { - -/*! - \class circular_buffer_space_optimized - \brief Space optimized circular buffer container adaptor. - T must be a copyable class or must have an noexcept move constructor - and move assignment operator. -*/ -template -class circular_buffer_space_optimized : -/*! \cond */ -#if BOOST_CB_ENABLE_DEBUG -public -#endif -/*! \endcond */ -circular_buffer { -public: -// Typedefs - - typedef typename circular_buffer::value_type value_type; - typedef typename circular_buffer::pointer pointer; - typedef typename circular_buffer::const_pointer const_pointer; - typedef typename circular_buffer::reference reference; - typedef typename circular_buffer::const_reference const_reference; - typedef typename circular_buffer::size_type size_type; - typedef typename circular_buffer::difference_type difference_type; - typedef typename circular_buffer::allocator_type allocator_type; - typedef typename circular_buffer::const_iterator const_iterator; - typedef typename circular_buffer::iterator iterator; - typedef typename circular_buffer::const_reverse_iterator const_reverse_iterator; - typedef typename circular_buffer::reverse_iterator reverse_iterator; - typedef typename circular_buffer::array_range array_range; - typedef typename circular_buffer::const_array_range const_array_range; - typedef typename circular_buffer::param_value_type param_value_type; - typedef typename circular_buffer::rvalue_type rvalue_type; - //typedef typename circular_buffer::return_value_type return_value_type; - -/*
 is not passed through to html or pdf. So 
is used in code section below. Ugly :-( -Ideally want a link to capacity_control, but this would require include details -and this would expose all the functions in details. -There must be a better way of doing this. -*/ - - /*! Capacity controller of the space optimized circular buffer. - - \see capacity_control in details.hpp. -

- -class capacity_control
-{
- size_type m_capacity; // Available capacity.
- size_type m_min_capacity; // Minimum capacity.
-public:
- capacity_control(size_type capacity, size_type min_capacity = 0)
- : m_capacity(capacity), m_min_capacity(min_capacity)
- {};
- size_type %capacity() const { return m_capacity; }
- size_type min_capacity() const { return m_min_capacity; }
- operator size_type() const { return m_capacity; }
-};
-
-

- - -

Always - capacity >= min_capacity. -

-

- The capacity() represents the capacity - of the circular_buffer_space_optimized and - the min_capacity() determines the minimal allocated size of its internal buffer. -

-

The converting constructor of the capacity_control allows implicit conversion from - size_type-like types which ensures compatibility of creating an instance of the - circular_buffer_space_optimized with other STL containers. - - On the other hand the operator %size_type() - provides implicit conversion to the size_type which allows to treat the - capacity of the circular_buffer_space_optimized the same way as in the - circular_buffer. -

- */ - typedef cb_details::capacity_control capacity_type; - -// Inherited - - using circular_buffer::get_allocator; - using circular_buffer::begin; - using circular_buffer::end; - using circular_buffer::rbegin; - using circular_buffer::rend; - using circular_buffer::at; - using circular_buffer::front; - using circular_buffer::back; - using circular_buffer::array_one; - using circular_buffer::array_two; - using circular_buffer::linearize; - using circular_buffer::is_linearized; - using circular_buffer::rotate; - using circular_buffer::size; - using circular_buffer::max_size; - using circular_buffer::empty; - -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) - reference operator [] (size_type n) { return circular_buffer::operator[](n); } - const_reference operator [] (size_type n) const { return circular_buffer::operator[](n); } -#else - using circular_buffer::operator[]; -#endif - -private: -// Member variables - - //! The capacity controller of the space optimized circular buffer. - capacity_type m_capacity_ctrl; - -public: -// Overridden - - //! Is the circular_buffer_space_optimized full? - /*! - \return true if the number of elements stored in the circular_buffer_space_optimized - equals the capacity of the circular_buffer_space_optimized; false otherwise. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer_space_optimized). - \sa empty() - */ - bool full() const BOOST_NOEXCEPT { return m_capacity_ctrl == size(); } - - /*! \brief Get the maximum number of elements which can be inserted into the - circular_buffer_space_optimized without overwriting any of already stored elements. - \return capacity().%capacity() - size() - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer_space_optimized). - \sa capacity(), size(), max_size() - */ - size_type reserve() const BOOST_NOEXCEPT { return m_capacity_ctrl - size(); } - - //! Get the capacity of the circular_buffer_space_optimized. - /*! - \return The capacity controller representing the maximum number of elements which can be stored in the - circular_buffer_space_optimized and the minimal allocated size of the internal buffer. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Does not invalidate any iterators. - \par Complexity - Constant (in the size of the circular_buffer_space_optimized). - \sa reserve(), size(), max_size(), - set_capacity(const capacity_type&) - */ - const capacity_type& capacity() const BOOST_NOEXCEPT { return m_capacity_ctrl; } - -#if defined(BOOST_CB_TEST) - - // Return the current capacity of the adapted circular buffer. - /* - \note This method is not intended to be used directly by the user. - It is defined only for testing purposes. - */ - size_type internal_capacity() const BOOST_NOEXCEPT { return circular_buffer::capacity(); } - -#endif // #if defined(BOOST_CB_TEST) - - /*! \brief Change the capacity (and the minimal guaranteed amount of allocated memory) of the - circular_buffer_space_optimized. - \post capacity() == capacity_ctrl \&\& size() \<= capacity_ctrl.capacity()

- If the current number of elements stored in the circular_buffer_space_optimized is greater - than the desired new capacity then number of [size() - capacity_ctrl.capacity()] last - elements will be removed and the new size will be equal to capacity_ctrl.capacity().

- If the current number of elements stored in the circular_buffer_space_optimized is lower - than the new capacity then the amount of allocated memory in the internal buffer may be accommodated as - necessary but it will never drop below capacity_ctrl.min_capacity(). - \param capacity_ctrl The new capacity controller. - \throws "An allocation error" if memory is exhausted, (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in min[size(), capacity_ctrl.%capacity()]). - \note To explicitly clear the extra allocated memory use the shrink-to-fit technique:

- %boost::%circular_buffer_space_optimized\ cb(1000);
- ...
- %boost::%circular_buffer_space_optimized\(cb).swap(cb);


- For more information about the shrink-to-fit technique in STL see - http://www.gotw.ca/gotw/054.htm. - \sa rset_capacity(const capacity_type&), - \link resize() resize(size_type, const_reference)\endlink - */ - void set_capacity(const capacity_type& capacity_ctrl) { - m_capacity_ctrl = capacity_ctrl; - if (capacity_ctrl < size()) { - iterator e = end(); - circular_buffer::erase(e - (size() - capacity_ctrl), e); - } - adjust_min_capacity(); - } - - //! Change the size of the circular_buffer_space_optimized. - /*! - \post size() == new_size \&\& capacity().%capacity() >= new_size

- If the new size is greater than the current size, copies of item will be inserted at the - back of the of the circular_buffer_space_optimized in order to achieve the desired - size. In the case the resulting size exceeds the current capacity the capacity will be set to - new_size.

- If the current number of elements stored in the circular_buffer_space_optimized is greater - than the desired new size then number of [size() - new_size] last elements will be - removed. (The capacity will remain unchanged.)

- The amount of allocated memory in the internal buffer may be accommodated as necessary. - \param new_size The new size. - \param item The element the circular_buffer_space_optimized will be filled with in order to gain - the requested size. (See the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the new size of the circular_buffer_space_optimized). - \sa \link rresize() rresize(size_type, const_reference)\endlink, - set_capacity(const capacity_type&) - */ - void resize(size_type new_size, param_value_type item = value_type()) { - if (new_size > size()) { - if (new_size > m_capacity_ctrl) - m_capacity_ctrl = capacity_type(new_size, m_capacity_ctrl.min_capacity()); - insert(end(), new_size - size(), item); - } else { - iterator e = end(); - erase(e - (size() - new_size), e); - } - } - - /*! \brief Change the capacity (and the minimal guaranteed amount of allocated memory) of the - circular_buffer_space_optimized. - \post capacity() == capacity_ctrl \&\& size() \<= capacity_ctrl

- If the current number of elements stored in the circular_buffer_space_optimized is greater - than the desired new capacity then number of [size() - capacity_ctrl.capacity()] - first elements will be removed and the new size will be equal to - capacity_ctrl.capacity().

- If the current number of elements stored in the circular_buffer_space_optimized is lower - than the new capacity then the amount of allocated memory in the internal buffer may be accommodated as - necessary but it will never drop below capacity_ctrl.min_capacity(). - \param capacity_ctrl The new capacity controller. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in min[size(), capacity_ctrl.%capacity()]). - \sa set_capacity(const capacity_type&), - \link rresize() rresize(size_type, const_reference)\endlink - */ - void rset_capacity(const capacity_type& capacity_ctrl) { - m_capacity_ctrl = capacity_ctrl; - if (capacity_ctrl < size()) { - iterator b = begin(); - circular_buffer::rerase(b, b + (size() - capacity_ctrl)); - } - adjust_min_capacity(); - } - - //! Change the size of the circular_buffer_space_optimized. - /*! - \post size() == new_size \&\& capacity().%capacity() >= new_size

- If the new size is greater than the current size, copies of item will be inserted at the - front of the of the circular_buffer_space_optimized in order to achieve the desired - size. In the case the resulting size exceeds the current capacity the capacity will be set to - new_size.

- If the current number of elements stored in the circular_buffer_space_optimized is greater - than the desired new size then number of [size() - new_size] first elements will be - removed. (The capacity will remain unchanged.)

- The amount of allocated memory in the internal buffer may be accommodated as necessary. - \param new_size The new size. - \param item The element the circular_buffer_space_optimized will be filled with in order to gain - the requested size. (See the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the new size of the circular_buffer_space_optimized). - \sa \link resize() resize(size_type, const_reference)\endlink, - rset_capacity(const capacity_type&) - */ - void rresize(size_type new_size, param_value_type item = value_type()) { - if (new_size > size()) { - if (new_size > m_capacity_ctrl) - m_capacity_ctrl = capacity_type(new_size, m_capacity_ctrl.min_capacity()); - rinsert(begin(), new_size - size(), item); - } else { - rerase(begin(), end() - new_size); - } - } - - //! Create an empty space optimized circular buffer with zero capacity. - /*! - \post capacity().%capacity() == 0 \&\& capacity().min_capacity() == 0 \&\& size() == 0 - \param alloc The allocator. - \throws Nothing. - \par Complexity - Constant. - \warning Since Boost version 1.36 the behaviour of this constructor has changed. Now it creates a space - optimized circular buffer with zero capacity. - */ - explicit circular_buffer_space_optimized(const allocator_type& alloc = allocator_type()) BOOST_NOEXCEPT - : circular_buffer(0, alloc) - , m_capacity_ctrl(0) {} - - //! Create an empty space optimized circular buffer with the specified capacity. - /*! - \post capacity() == capacity_ctrl \&\& size() == 0

- The amount of allocated memory in the internal buffer is capacity_ctrl.min_capacity(). - \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in - the circular_buffer_space_optimized and the minimal allocated size of the - internal buffer. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Complexity - Constant. - */ - explicit circular_buffer_space_optimized(capacity_type capacity_ctrl, - const allocator_type& alloc = allocator_type()) - : circular_buffer(capacity_ctrl.min_capacity(), alloc) - , m_capacity_ctrl(capacity_ctrl) {} - - /*! \brief Create a full space optimized circular buffer with the specified capacity filled with - capacity_ctrl.%capacity() copies of item. - \post capacity() == capacity_ctrl \&\& full() \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... - \&\& (*this) [capacity_ctrl.%capacity() - 1] == item

- The amount of allocated memory in the internal buffer is capacity_ctrl.capacity(). - \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in - the circular_buffer_space_optimized and the minimal allocated size of the - internal buffer. - \param item The element the created circular_buffer_space_optimized will be filled with. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \throws Whatever T::T(const T&) throws. - \par Complexity - Linear (in the capacity_ctrl.%capacity()). - */ - circular_buffer_space_optimized(capacity_type capacity_ctrl, param_value_type item, - const allocator_type& alloc = allocator_type()) - : circular_buffer(capacity_ctrl.capacity(), item, alloc) - , m_capacity_ctrl(capacity_ctrl) {} - - /*! \brief Create a space optimized circular buffer with the specified capacity filled with n copies - of item. - \pre capacity_ctrl.%capacity() >= n - \post capacity() == capacity_ctrl \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item - \&\& ... \&\& (*this)[n - 1] == item

- The amount of allocated memory in the internal buffer is - max[n, capacity_ctrl.min_capacity()]. - \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in - the circular_buffer_space_optimized and the minimal allocated size of the - internal buffer. - \param n The number of elements the created circular_buffer_space_optimized will be filled with. - \param item The element the created circular_buffer_space_optimized will be filled with. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the n). - */ - circular_buffer_space_optimized(capacity_type capacity_ctrl, size_type n, param_value_type item, - const allocator_type& alloc = allocator_type()) - : circular_buffer(init_capacity(capacity_ctrl, n), n, item, alloc) - , m_capacity_ctrl(capacity_ctrl) {} - - //! The copy constructor. - /*! - Creates a copy of the specified circular_buffer_space_optimized. - \post *this == cb

- The amount of allocated memory in the internal buffer is cb.size(). - \param cb The circular_buffer_space_optimized to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in the size of cb). - */ - circular_buffer_space_optimized(const circular_buffer_space_optimized& cb) - : circular_buffer(cb.begin(), cb.end(), cb.get_allocator()) - , m_capacity_ctrl(cb.m_capacity_ctrl) {} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - //! The move constructor. - /*! \brief Move constructs a circular_buffer_space_optimized from cb, - leaving cb empty. - \pre C++ compiler with rvalue references support. - \post cb.empty() - \param cb circular_buffer to 'steal' value from. - \throws Nothing. - \par Constant. - */ - circular_buffer_space_optimized(circular_buffer_space_optimized&& cb) BOOST_NOEXCEPT - : circular_buffer() - , m_capacity_ctrl(0) { - cb.swap(*this); - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - //! Create a full space optimized circular buffer filled with a copy of the range. - /*! - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\& - full() \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& - (*this)[std::distance(first, last) - 1] == *(last - 1)

- The amount of allocated memory in the internal buffer is std::distance(first, last). - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept - and InputIterator is a move iterator. - \par Complexity - Linear (in the std::distance(first, last)). - */ - template - circular_buffer_space_optimized(InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()) - : circular_buffer(first, last, alloc) - , m_capacity_ctrl(circular_buffer::capacity()) {} - - /*! \brief Create a space optimized circular buffer with the specified capacity (and the minimal guaranteed amount - of allocated memory) filled with a copy of the range. - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\& (*this)[0]== - *(last - capacity_ctrl.%capacity()) \&\& (*this)[1] == *(last - capacity_ctrl.%capacity() + 1) \&\& ... - \&\& (*this)[capacity_ctrl.%capacity() - 1] == *(last - 1)

- If the number of items to be copied from the range [first, last) is greater than the - specified capacity_ctrl.%capacity() then only elements from the range - [last - capacity_ctrl.%capacity(), last) will be copied.

- The amount of allocated memory in the internal buffer is max[capacity_ctrl.min_capacity(), - min[capacity_ctrl.%capacity(), std::distance(first, last)]]. - \param capacity_ctrl The capacity controller representing the maximum number of elements which can be stored in - the circular_buffer_space_optimized and the minimal allocated size of the - internal buffer. - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \param alloc The allocator. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Complexity - Linear (in std::distance(first, last); in - min[capacity_ctrl.%capacity(), std::distance(first, last)] if the InputIterator - is a RandomAccessIterator). - */ - template - circular_buffer_space_optimized(capacity_type capacity_ctrl, InputIterator first, InputIterator last, - const allocator_type& alloc = allocator_type()) - : circular_buffer( - init_capacity(capacity_ctrl, first, last, is_integral()), - first, last, alloc) - , m_capacity_ctrl(capacity_ctrl) { - reduce_capacity( - is_same< BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category, std::input_iterator_tag >()); - } - -#if defined(BOOST_CB_NEVER_DEFINED) -// This section will never be compiled - the default destructor will be generated instead. -// Declared only for documentation purpose. - - //! The destructor. - /*! - Destroys the circular_buffer_space_optimized. - \throws Nothing. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (including - iterators equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa clear() - */ - ~circular_buffer_space_optimized(); - - //! no-comment - void erase_begin(size_type n); - - //! no-comment - void erase_end(size_type n); - -#endif // #if defined(BOOST_CB_NEVER_DEFINED) - - //! The assign operator. - /*! - Makes this circular_buffer_space_optimized to become a copy of the specified - circular_buffer_space_optimized. - \post *this == cb

- The amount of allocated memory in the internal buffer is cb.size(). - \param cb The circular_buffer_space_optimized to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \throws Whatever T::T(const T&) throws. - \par Exception Safety - Strong. - \par Iterator Invalidation - Invalidates all iterators pointing to this circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of cb). - \sa \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - circular_buffer_space_optimized& operator = (const circular_buffer_space_optimized& cb) { - if (this == &cb) - return *this; - circular_buffer::assign(cb.begin(), cb.end()); - m_capacity_ctrl = cb.m_capacity_ctrl; - return *this; - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - /*! \brief Move assigns content of cb to *this, leaving cb empty. - \pre C++ compiler with rvalue references support. - \post cb.empty() - \param cb circular_buffer to 'steal' value from. - \throws Nothing. - \par Complexity - Constant. - */ - circular_buffer_space_optimized& operator = (circular_buffer_space_optimized&& cb) BOOST_NOEXCEPT { - cb.swap(*this); // now `this` holds `cb` - circular_buffer(get_allocator()) // temporary that holds initial `cb` allocator - .swap(cb); // makes `cb` empty - return *this; - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - - //! Assign n items into the space optimized circular buffer. - /*! - The content of the circular_buffer_space_optimized will be removed and replaced with - n copies of the item. - \post capacity().%capacity() == n \&\& capacity().min_capacity() == 0 \&\& size() == n \&\& (*this)[0] == - item \&\& (*this)[1] == item \&\& ... \&\& (*this) [n - 1] == item

- The amount of allocated memory in the internal buffer is n. - \param n The number of elements the circular_buffer_space_optimized will be filled with. - \param item The element the circular_buffer_space_optimized will be filled with. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the n). - \sa \link operator=(const circular_buffer_space_optimized&) operator=\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - void assign(size_type n, param_value_type item) { - circular_buffer::assign(n, item); - m_capacity_ctrl = capacity_type(n); - } - - //! Assign n items into the space optimized circular buffer specifying the capacity. - /*! - The capacity of the circular_buffer_space_optimized will be set to the specified value and the - content of the circular_buffer_space_optimized will be removed and replaced with n - copies of the item. - \pre capacity_ctrl.%capacity() >= n - \post capacity() == capacity_ctrl \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item - \&\& ... \&\& (*this) [n - 1] == item

- The amount of allocated memory will be max[n, capacity_ctrl.min_capacity()]. - \param capacity_ctrl The new capacity controller. - \param n The number of elements the circular_buffer_space_optimized will be filled with. - \param item The element the circular_buffer_space_optimized will be filled with. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the n). - \sa \link operator=(const circular_buffer_space_optimized&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - assign(InputIterator, InputIterator), - assign(capacity_type, InputIterator, InputIterator) - */ - void assign(capacity_type capacity_ctrl, size_type n, param_value_type item) { - BOOST_CB_ASSERT(capacity_ctrl.capacity() >= n); // check for new capacity lower than n - circular_buffer::assign((std::max)(capacity_ctrl.min_capacity(), n), n, item); - m_capacity_ctrl = capacity_ctrl; - } - - //! Assign a copy of the range into the space optimized circular buffer. - /*! - The content of the circular_buffer_space_optimized will be removed and replaced with copies of - elements from the specified range. - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity().%capacity() == std::distance(first, last) \&\& capacity().min_capacity() == 0 \&\& - size() == std::distance(first, last) \&\& (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... - \&\& (*this)[std::distance(first, last) - 1] == *(last - 1)

- The amount of allocated memory in the internal buffer is std::distance(first, last). - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept and - InputIterator is a move iterator. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the std::distance(first, last)). - \sa \link operator=(const circular_buffer_space_optimized&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(capacity_type, InputIterator, InputIterator) - */ - template - void assign(InputIterator first, InputIterator last) { - circular_buffer::assign(first, last); - m_capacity_ctrl = capacity_type(circular_buffer::capacity()); - } - - //! Assign a copy of the range into the space optimized circular buffer specifying the capacity. - /*! - The capacity of the circular_buffer_space_optimized will be set to the specified value and the - content of the circular_buffer_space_optimized will be removed and replaced with copies of - elements from the specified range. - \pre Valid range [first, last).
- first and last have to meet the requirements of - InputIterator. - \post capacity() == capacity_ctrl \&\& size() \<= std::distance(first, last) \&\& - (*this)[0]== *(last - capacity) \&\& (*this)[1] == *(last - capacity + 1) \&\& ... \&\& - (*this)[capacity - 1] == *(last - 1)

- If the number of items to be copied from the range [first, last) is greater than the - specified capacity then only elements from the range [last - capacity, last) - will be copied.

The amount of allocated memory in the internal buffer is - max[std::distance(first, last), capacity_ctrl.min_capacity()]. - \param capacity_ctrl The new capacity controller. - \param first The beginning of the range to be copied. - \param last The end of the range to be copied. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept and - InputIterator is a move iterator. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in std::distance(first, last); in - min[capacity_ctrl.%capacity(), std::distance(first, last)] if the InputIterator - is a RandomAccessIterator). - \sa \link operator=(const circular_buffer_space_optimized&) operator=\endlink, - \link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink, - \link assign(capacity_type, size_type, param_value_type) - assign(capacity_type, size_type, const_reference)\endlink, - assign(InputIterator, InputIterator) - */ - template - void assign(capacity_type capacity_ctrl, InputIterator first, InputIterator last) { - m_capacity_ctrl = capacity_ctrl; - circular_buffer::assign(capacity_ctrl, first, last); - } - - //! Swap the contents of two space-optimized circular-buffers. - /*! - \post this contains elements of cb and vice versa; the capacity and the amount of - allocated memory in the internal buffer of this equal to the capacity and the amount of - allocated memory of cb and vice versa. - \param cb The circular_buffer_space_optimized whose content will be swapped. - \throws Nothing. - \par Exception Safety - No-throw. - \par Iterator Invalidation - Invalidates all iterators of both circular_buffer_space_optimized containers. (On the other - hand the iterators still point to the same elements but within another container. If you want to rely on - this feature you have to turn the __debug_support off, - otherwise an assertion will report an error if such invalidated iterator is used.) - \par Complexity - Constant (in the size of the circular_buffer_space_optimized). - \sa swap(circular_buffer&, circular_buffer&), - swap(circular_buffer_space_optimized&, circular_buffer_space_optimized&) - - - */ - // Note link does not work right. Asked on Doxygen forum for advice 23 May 2103. - - void swap(circular_buffer_space_optimized& cb) BOOST_NOEXCEPT { - std::swap(m_capacity_ctrl, cb.m_capacity_ctrl); - circular_buffer::swap(cb); - } - - //! Insert a new element at the end of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then back() == item
- If the circular_buffer_space_optimized is full, the first element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param item The element to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_front() push_front(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_back(param_value_type item) { - check_low_capacity(); - circular_buffer::push_back(item); - } - - //! Insert a new element at the end of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then back() == item
- If the circular_buffer_space_optimized is full, the first element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param item The element to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_front() push_front(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_back(rvalue_type item) { - check_low_capacity(); - circular_buffer::push_back(boost::move(item)); - } - - //! Insert a new element at the end of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then back() == item
- If the circular_buffer_space_optimized is full, the first element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T() throws. - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_front() push_front(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_back() { - check_low_capacity(); - circular_buffer::push_back(); - } - - //! Insert a new element at the beginning of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then front() == item
- If the circular_buffer_space_optimized is full, the last element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param item The element to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_back() push_back(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_front(param_value_type item) { - check_low_capacity(); - circular_buffer::push_front(item); - } - - //! Insert a new element at the beginning of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then front() == item
- If the circular_buffer_space_optimized is full, the last element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param item The element to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_back() push_back(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_front(rvalue_type item) { - check_low_capacity(); - circular_buffer::push_front(boost::move(item)); - } - - //! Insert a new element at the beginning of the space optimized circular buffer. - /*! - \post if capacity().%capacity() > 0 then front() == item
- If the circular_buffer_space_optimized is full, the last element will be removed. If the - capacity is 0, nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T() throws. - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link push_back() push_back(const_reference)\endlink, pop_back(), - pop_front() - */ - void push_front() { - check_low_capacity(); - circular_buffer::push_front(); - } - - //! Remove the last element from the space optimized circular buffer. - /*! - \pre !empty() - \post The last element is removed from the circular_buffer_space_optimized.

- The amount of allocated memory in the internal buffer may be predictively decreased. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa pop_front(), \link push_back() push_back(const_reference)\endlink, - \link push_front() push_front(const_reference)\endlink - */ - void pop_back() { - circular_buffer::pop_back(); - check_high_capacity(); - } - - //! Remove the first element from the space optimized circular buffer. - /*! - \pre !empty() - \post The first element is removed from the circular_buffer_space_optimized.

- The amount of allocated memory in the internal buffer may be predictively decreased. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa pop_back(), \link push_back() push_back(const_reference)\endlink, - \link push_front() push_front(const_reference)\endlink - */ - void pop_front() { - circular_buffer::pop_front(); - check_high_capacity(); - } - - //! Insert an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted at the position pos.
- If the circular_buffer_space_optimized is full, the first element will be overwritten. If - the circular_buffer_space_optimized is full and the pos points to - begin(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos, param_value_type item) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::insert(begin() + index, item); - } - - //! Insert an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted at the position pos.
- If the circular_buffer_space_optimized is full, the first element will be overwritten. If - the circular_buffer_space_optimized is full and the pos points to - begin(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos, rvalue_type item) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::insert(begin() + index, boost::move(item)); - } - - //! Insert an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted at the position pos.
- If the circular_buffer_space_optimized is full, the first element will be overwritten. If - the circular_buffer_space_optimized is full and the pos points to - begin(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the item will be inserted. - \return Iterator to the inserted element or begin() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T() throws. - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - iterator insert(iterator pos) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::insert(begin() + index); - } - - //! Insert n copies of the item at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The number of min[n, (pos - begin()) + reserve()] elements will be inserted at the position - pos.
The number of min[pos - begin(), max[0, n - reserve()]] elements will - be overwritten at the beginning of the circular_buffer_space_optimized.
(See - Example for the explanation.)

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the items will be inserted. - \param n The number of items the to be inserted. - \param item The element whose copies will be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in min[capacity().%capacity(), size() + n]). - \par Example - Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its - internal buffer may look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting 5 elements at the position p:

- insert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements - 1 and 2 are overwritten. This is due to the fact the insert operation preserves - the capacity. After insertion the internal buffer looks like this:

|0|0|0|0|3|4|
-
For comparison if the capacity would not be preserved the internal buffer would then result in - |1|2|0|0|0|0|0|3|4|. - \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - insert(iterator, InputIterator, InputIterator), - \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - void insert(iterator pos, size_type n, param_value_type item) { - size_type index = pos - begin(); - check_low_capacity(n); - circular_buffer::insert(begin() + index, n, item); - } - - //! Insert the range [first, last) at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end.
Valid range [first, last) where first and last meet the - requirements of an InputIterator. - \post Elements from the range - [first + max[0, distance(first, last) - (pos - begin()) - reserve()], last) will be - inserted at the position pos.
The number of min[pos - begin(), max[0, - distance(first, last) - reserve()]] elements will be overwritten at the beginning of the - circular_buffer_space_optimized.
(See Example for the explanation.)

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the range will be inserted. - \param first The beginning of the range to be inserted. - \param last The end of the range to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in [size() + std::distance(first, last)]; in - min[capacity().%capacity(), size() + std::distance(first, last)] if the - InputIterator is a - RandomAccessIterator). - \par Example - Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its - internal buffer may look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting a range of elements at the position p:

- int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

- actually only elements 6, 7, 8 and 9 from the - specified range get inserted and elements 1 and 2 are overwritten. This is due - to the fact the insert operation preserves the capacity. After insertion the internal buffer looks like - this:

|6|7|8|9|3|4|

For comparison if the capacity would not be preserved the - internal buffer would then result in |1|2|5|6|7|8|9|3|4|. - \sa \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, \link rinsert(iterator, param_value_type) - rinsert(iterator, value_type)\endlink, \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator) - */ - template - void insert(iterator pos, InputIterator first, InputIterator last) { - insert(pos, first, last, is_integral()); - } - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted before the position pos.
- If the circular_buffer_space_optimized is full, the last element will be overwritten. If the - circular_buffer_space_optimized is full and the pos points to - end(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position before which the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos, param_value_type item) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::rinsert(begin() + index, item); - } - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted before the position pos.
- If the circular_buffer_space_optimized is full, the last element will be overwritten. If the - circular_buffer_space_optimized is full and the pos points to - end(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position before which the item will be inserted. - \param item The element to be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos, rvalue_type item) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::rinsert(begin() + index, boost::move(item)); - } - - //! Insert an element before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The item will be inserted before the position pos.
- If the circular_buffer_space_optimized is full, the last element will be overwritten. If the - circular_buffer_space_optimized is full and the pos points to - end(), then the item will not be inserted. If the capacity is 0, - nothing will be inserted.

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position before which the item will be inserted. - \return Iterator to the inserted element or end() if the item is not inserted. (See - the Effect.) - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T() throws. - Whatever T::T(const T&) throws or nothing if T::T(T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - iterator rinsert(iterator pos) { - size_type index = pos - begin(); - check_low_capacity(); - return circular_buffer::rinsert(begin() + index); - } - - //! Insert n copies of the item before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end. - \post The number of min[n, (end() - pos) + reserve()] elements will be inserted before the - position pos.
The number of min[end() - pos, max[0, n - reserve()]] elements - will be overwritten at the end of the circular_buffer_space_optimized.
(See - Example for the explanation.)

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the items will be inserted. - \param n The number of items the to be inserted. - \param item The element whose copies will be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in min[capacity().%capacity(), size() + n]). - \par Example - Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its - internal buffer may look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting 5 elements before the position p:

- rinsert(p, (size_t)5, 0);

actually only 4 elements get inserted and elements - 3 and 4 are overwritten. This is due to the fact the rinsert operation preserves - the capacity. After insertion the internal buffer looks like this:

|1|2|0|0|0|0|
-
For comparison if the capacity would not be preserved the internal buffer would then result in - |1|2|0|0|0|0|0|3|4|. - \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - rinsert(iterator, InputIterator, InputIterator), - \link insert(iterator, param_value_type) insert(iterator, value_type)\endlink, - \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - void rinsert(iterator pos, size_type n, param_value_type item) { - size_type index = pos - begin(); - check_low_capacity(n); - circular_buffer::rinsert(begin() + index, n, item); - } - - //! Insert the range [first, last) before the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized or its - end.
- Valid range [first, last) where first and last meet the - requirements of an InputIterator. - \post Elements from the range - [first, last - max[0, distance(first, last) - (end() - pos) - reserve()]) will be inserted - before the position pos.
The number of min[end() - pos, max[0, - distance(first, last) - reserve()]] elements will be overwritten at the end of the - circular_buffer.
(See Example for the explanation.)

- The amount of allocated memory in the internal buffer may be predictively increased. - \param pos An iterator specifying the position where the range will be inserted. - \param first The beginning of the range to be inserted. - \param last The end of the range to be inserted. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::T(const T&) throws. - Whatever T::operator = (const T&) throws. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in [size() + std::distance(first, last)]; in - min[capacity().%capacity(), size() + std::distance(first, last)] if the - InputIterator is a - RandomAccessIterator). - \par Example - Consider a circular_buffer_space_optimized with the capacity of 6 and the size of 4. Its - internal buffer may look like the one below.

- |1|2|3|4| | |
- p ___^

After inserting a range of elements before the position p:

- int array[] = { 5, 6, 7, 8, 9 };
insert(p, array, array + 5);

- actually only elements 5, 6, 7 and 8 from the - specified range get inserted and elements 3 and 4 are overwritten. This is due - to the fact the rinsert operation preserves the capacity. After insertion the internal buffer looks like - this:

|1|2|5|6|7|8|

For comparison if the capacity would not be preserved the - internal buffer would then result in |1|2|5|6|7|8|9|3|4|. - \sa \link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink, - \link rinsert(iterator, size_type, param_value_type) - rinsert(iterator, size_type, value_type)\endlink, \link insert(iterator, param_value_type) - insert(iterator, value_type)\endlink, \link insert(iterator, size_type, param_value_type) - insert(iterator, size_type, value_type)\endlink, - insert(iterator, InputIterator, InputIterator) - */ - template - void rinsert(iterator pos, InputIterator first, InputIterator last) { - rinsert(pos, first, last, is_integral()); - } - - //! Remove an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized (but not - an end()). - \post The element at the position pos is removed.

- The amount of allocated memory in the internal buffer may be predictively decreased. - \param pos An iterator pointing at the element to be removed. - \return Iterator to the first element remaining beyond the removed element or end() if no such - element exists. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::operator = (const T&) throws or - nothing if T::operator = (T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa erase(iterator, iterator), rerase(iterator), - rerase(iterator, iterator), clear() - */ - iterator erase(iterator pos) { - iterator it = circular_buffer::erase(pos); - size_type index = it - begin(); - check_high_capacity(); - return begin() + index; - } - - //! Erase the range [first, last). - /*! - \pre Valid range [first, last). - \post The elements from the range [first, last) are removed. (If first == last - nothing is removed.)

- The amount of allocated memory in the internal buffer may be predictively decreased. - \param first The beginning of the range to be removed. - \param last The end of the range to be removed. - \return Iterator to the first element remaining beyond the removed elements or end() if no such - element exists. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::operator = (const T&) throws or - nothing if T::operator = (T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa erase(iterator), rerase(iterator), rerase(iterator, iterator), - clear() - */ - iterator erase(iterator first, iterator last) { - iterator it = circular_buffer::erase(first, last); - size_type index = it - begin(); - check_high_capacity(); - return begin() + index; - } - - //! Remove an element at the specified position. - /*! - \pre pos is a valid iterator pointing to the circular_buffer_space_optimized (but not - an end()).

- The amount of allocated memory in the internal buffer may be predictively decreased. - \post The element at the position pos is removed. - \param pos An iterator pointing at the element to be removed. - \return Iterator to the first element remaining in front of the removed element or begin() if no - such element exists. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::operator = (const T&) throws or - nothing if T::operator = (T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \note Basically there is no difference between erase(iterator) and this method. It is implemented - only for consistency with the base circular_buffer. - \sa erase(iterator), erase(iterator, iterator), - rerase(iterator, iterator), clear() - */ - iterator rerase(iterator pos) { - iterator it = circular_buffer::rerase(pos); - size_type index = it - begin(); - check_high_capacity(); - return begin() + index; - } - - //! Erase the range [first, last). - /*! - \pre Valid range [first, last). - \post The elements from the range [first, last) are removed. (If first == last - nothing is removed.)

- The amount of allocated memory in the internal buffer may be predictively decreased. - \param first The beginning of the range to be removed. - \param last The end of the range to be removed. - \return Iterator to the first element remaining in front of the removed elements or begin() if no - such element exists. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - Whatever T::operator = (const T&) throws or - nothing if T::operator = (T&&) is noexcept. - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \note Basically there is no difference between erase(iterator, iterator) and this method. It is - implemented only for consistency with the base - . - \sa erase(iterator), erase(iterator, iterator), rerase(iterator), - clear() - */ - iterator rerase(iterator first, iterator last) { - iterator it = circular_buffer::rerase(first, last); - size_type index = it - begin(); - check_high_capacity(); - return begin() + index; - } - - //! Remove all stored elements from the space optimized circular buffer. - /*! - \post size() == 0

- The amount of allocated memory in the internal buffer may be predictively decreased. - \throws "An allocation error" if memory is exhausted (std::bad_alloc if the standard allocator is - used). - \par Exception Safety - Basic. - \par Iterator Invalidation - Invalidates all iterators pointing to the circular_buffer_space_optimized (except iterators - equal to end()). - \par Complexity - Linear (in the size of the circular_buffer_space_optimized). - \sa ~circular_buffer_space_optimized(), erase(iterator), - erase(iterator, iterator), rerase(iterator), - rerase(iterator, iterator) - */ - void clear() { erase(begin(), end()); } - -private: -// Helper methods - - /*! INTERNAL ONLY */ - void adjust_min_capacity() { - if (m_capacity_ctrl.min_capacity() > circular_buffer::capacity()) - circular_buffer::set_capacity(m_capacity_ctrl.min_capacity()); - else - check_high_capacity(); - } - - /*! INTERNAL ONLY */ - size_type ensure_reserve(size_type new_capacity, size_type buffer_size) const { - if (buffer_size + new_capacity / 5 >= new_capacity) - new_capacity *= 2; // ensure at least 20% reserve - if (new_capacity > m_capacity_ctrl) - return m_capacity_ctrl; - return new_capacity; - } - - /*! INTERNAL ONLY */ - void check_low_capacity(size_type n = 1) { - size_type new_size = size() + n; - size_type new_capacity = circular_buffer::capacity(); - if (new_size > new_capacity) { - if (new_capacity == 0) - new_capacity = 1; - for (; new_size > new_capacity; new_capacity *= 2) {} - circular_buffer::set_capacity( - ensure_reserve(new_capacity, new_size)); - } -#if BOOST_CB_ENABLE_DEBUG - this->invalidate_iterators_except(end()); -#endif - } - - /*! INTERNAL ONLY */ - void check_high_capacity() { - size_type new_capacity = circular_buffer::capacity(); - while (new_capacity / 3 >= size()) { // (new_capacity / 3) -> avoid oscillations - new_capacity /= 2; - if (new_capacity <= m_capacity_ctrl.min_capacity()) { - new_capacity = m_capacity_ctrl.min_capacity(); - break; - } - } - circular_buffer::set_capacity( - ensure_reserve(new_capacity, size())); -#if BOOST_CB_ENABLE_DEBUG - this->invalidate_iterators_except(end()); -#endif - } - - /*! INTERNAL ONLY */ - void reduce_capacity(const true_type&) { - circular_buffer::set_capacity((std::max)(m_capacity_ctrl.min_capacity(), size())); - } - - /*! INTERNAL ONLY */ - void reduce_capacity(const false_type&) {} - - /*! INTERNAL ONLY */ - static size_type init_capacity(const capacity_type& capacity_ctrl, size_type n) { - BOOST_CB_ASSERT(capacity_ctrl.capacity() >= n); // check for capacity lower than n - return (std::max)(capacity_ctrl.min_capacity(), n); - } - - /*! INTERNAL ONLY */ - template - static size_type init_capacity(const capacity_type& capacity_ctrl, IntegralType n, IntegralType, - const true_type&) { - return init_capacity(capacity_ctrl, static_cast(n)); - } - - /*! INTERNAL ONLY */ - template - static size_type init_capacity(const capacity_type& capacity_ctrl, Iterator first, Iterator last, - const false_type&) { - BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) - return init_capacity(capacity_ctrl, first, last, std::iterator_traits::iterator_category()); -#else - return init_capacity( - capacity_ctrl, first, last, BOOST_DEDUCED_TYPENAME std::iterator_traits::iterator_category()); -#endif - } - - /*! INTERNAL ONLY */ - template - static size_type init_capacity(const capacity_type& capacity_ctrl, InputIterator, InputIterator, - const std::input_iterator_tag&) { - return capacity_ctrl.capacity(); - } - - /*! INTERNAL ONLY */ - template - static size_type init_capacity(const capacity_type& capacity_ctrl, ForwardIterator first, ForwardIterator last, - const std::forward_iterator_tag&) { - BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range - return (std::max)(capacity_ctrl.min_capacity(), - (std::min)(capacity_ctrl.capacity(), static_cast(std::distance(first, last)))); - } - - /*! INTERNAL ONLY */ - template - void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { - insert(pos, static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) { - size_type index = pos - begin(); - check_low_capacity(std::distance(first, last)); - circular_buffer::insert(begin() + index, first, last); - } - - /*! INTERNAL ONLY */ - template - void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) { - rinsert(pos, static_cast(n), static_cast(item)); - } - - /*! INTERNAL ONLY */ - template - void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) { - size_type index = pos - begin(); - check_low_capacity(std::distance(first, last)); - circular_buffer::rinsert(begin() + index, first, last); - } -}; - -// Non-member functions - -//! Test two space optimized circular buffers for equality. -template -inline bool operator == (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return lhs.size() == rhs.size() && - std::equal(lhs.begin(), lhs.end(), rhs.begin()); -} - -//! Lexicographical comparison. -template -inline bool operator < (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return std::lexicographical_compare( - lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); -} - -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) - -//! Test two space optimized circular buffers for non-equality. -template -inline bool operator != (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return !(lhs == rhs); -} - -//! Lexicographical comparison. -template -inline bool operator > (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return rhs < lhs; -} - -//! Lexicographical comparison. -template -inline bool operator <= (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return !(rhs < lhs); -} - -//! Lexicographical comparison. -template -inline bool operator >= (const circular_buffer_space_optimized& lhs, - const circular_buffer_space_optimized& rhs) { - return !(lhs < rhs); -} - -//! Swap the contents of two space optimized circular buffers. -template -inline void swap(circular_buffer_space_optimized& lhs, - circular_buffer_space_optimized& rhs) BOOST_NOEXCEPT { - lhs.swap(rhs); -} - -#endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) - -} // namespace boost - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_SPACE_OPTIMIZED_HPP) diff --git a/boost/circular_buffer_fwd.hpp b/boost/circular_buffer_fwd.hpp deleted file mode 100644 index 621fb95..0000000 --- a/boost/circular_buffer_fwd.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Forward declaration of the circular buffer and its adaptor. - -// Copyright (c) 2003-2008 Jan Gaspar - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See www.boost.org/libs/circular_buffer for documentation. - -#if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) -#define BOOST_CIRCULAR_BUFFER_FWD_HPP - -#if defined(_MSC_VER) - #pragma once -#endif - -#include -#if !defined(BOOST_NO_STD_ALLOCATOR) - #include -#else - #include -#endif - -namespace boost { - -#if !defined(BOOST_NO_STD_ALLOCATOR) - #define BOOST_CB_DEFAULT_ALLOCATOR(T) std::allocator -#else - #define BOOST_CB_DEFAULT_ALLOCATOR(T) BOOST_DEDUCED_TYPENAME std::vector::allocator_type -#endif - -template -class circular_buffer; - -template -class circular_buffer_space_optimized; - -#undef BOOST_CB_DEFAULT_ALLOCATOR - -} // namespace boost - -#endif // #if !defined(BOOST_CIRCULAR_BUFFER_FWD_HPP) diff --git a/boost/container_hash/detail/requires_cxx11.hpp b/boost/container_hash/detail/requires_cxx11.hpp index 61db135..f123f92 100644 --- a/boost/container_hash/detail/requires_cxx11.hpp +++ b/boost/container_hash/detail/requires_cxx11.hpp @@ -15,7 +15,7 @@ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_HDR_TUPLE) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.ContainerHash 1.82 and will be removed in Boost.ContainerHash 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.ContainerHash 1.82 and will be removed in Boost.ContainerHash 1.84. Please open an issue in https://github.com/boostorg/container_hash if you want it retained.") #endif diff --git a/boost/core/bit.hpp b/boost/core/bit.hpp index 5d14685..a6147e4 100644 --- a/boost/core/bit.hpp +++ b/boost/core/bit.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #if defined(_MSC_VER) @@ -38,6 +39,20 @@ #endif // defined(_MSC_VER) +#if defined(BOOST_MSVC) && BOOST_MSVC >= 1925 +# define BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL +#endif + +#if defined(__has_builtin) +# if __has_builtin(__builtin_bit_cast) +# define BOOST_CORE_HAS_BUILTIN_BIT_CAST +# endif +#endif + +#if defined(BOOST_MSVC) && BOOST_MSVC >= 1926 +# define BOOST_CORE_HAS_BUILTIN_BIT_CAST +#endif + namespace boost { namespace core @@ -45,6 +60,16 @@ namespace core // bit_cast +#if defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST) + +template +BOOST_CONSTEXPR To bit_cast( From const & from ) BOOST_NOEXCEPT +{ + return __builtin_bit_cast( To, from ); +} + +#else + template To bit_cast( From const & from ) BOOST_NOEXCEPT { @@ -55,6 +80,8 @@ To bit_cast( From const & from ) BOOST_NOEXCEPT return to; } +#endif + // countl #if defined(__GNUC__) || defined(__clang__) @@ -102,10 +129,51 @@ BOOST_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT namespace detail { +#if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + constexpr unsigned char mod37[ 37 ] = { 32, 31, 6, 30, 9, 5, 0, 29, 16, 8, 2, 4, 21, 0, 19, 28, 25, 15, 0, 7, 10, 1, 17, 3, 22, 20, 26, 0, 11, 18, 23, 27, 12, 24, 13, 14, 0 }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return mod37[ x % 37 ]; + } + else + { + unsigned long r; + + if( _BitScanReverse( &r, x ) ) + { + return 31 - static_cast( r ); + } + else + { + return 32; + } + } +} + +BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countl_impl( static_cast( x ) ) - 24; +} + +BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countl_impl( static_cast( x ) ) - 16; +} + +#elif defined(_MSC_VER) + inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT { -#if defined(_MSC_VER) - unsigned long r; if( _BitScanReverse( &r, x ) ) @@ -116,44 +184,6 @@ inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT { return 32; } - -#else - - static unsigned char const mod37[ 37 ] = { 32, 31, 6, 30, 9, 5, 0, 29, 16, 8, 2, 4, 21, 0, 19, 28, 25, 15, 0, 7, 10, 1, 17, 3, 22, 20, 26, 0, 11, 18, 23, 27, 12, 24, 13, 14, 0 }; - - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - - return mod37[ x % 37 ]; - -#endif -} - -inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT -{ -#if defined(_MSC_VER) && defined(_M_X64) - - unsigned long r; - - if( _BitScanReverse64( &r, x ) ) - { - return 63 - static_cast( r ); - } - else - { - return 64; - } - -#else - - return static_cast( x >> 32 ) != 0? - boost::core::detail::countl_impl( static_cast( x >> 32 ) ): - boost::core::detail::countl_impl( static_cast( x ) ) + 32; - -#endif } inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT @@ -166,10 +196,98 @@ inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT return boost::core::detail::countl_impl( static_cast( x ) ) - 16; } +#else + +inline int countl_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + static unsigned char const mod37[ 37 ] = { 32, 31, 6, 30, 9, 5, 0, 29, 16, 8, 2, 4, 21, 0, 19, 28, 25, 15, 0, 7, 10, 1, 17, 3, 22, 20, 26, 0, 11, 18, 23, 27, 12, 24, 13, 14, 0 }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return mod37[ x % 37 ]; +} + +inline int countl_impl( boost::uint8_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countl_impl( static_cast( x ) ) - 24; +} + +inline int countl_impl( boost::uint16_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countl_impl( static_cast( x ) ) - 16; +} + +#endif + +#if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + return static_cast( x >> 32 ) != 0? + boost::core::detail::countl_impl( static_cast( x >> 32 ) ): + boost::core::detail::countl_impl( static_cast( x ) ) + 32; + } + else + { + unsigned long r; + + if( _BitScanReverse64( &r, x ) ) + { + return 63 - static_cast( r ); + } + else + { + return 64; + } + } +} + +#elif defined(_MSC_VER) && defined(_M_X64) + +inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + unsigned long r; + + if( _BitScanReverse64( &r, x ) ) + { + return 63 - static_cast( r ); + } + else + { + return 64; + } +} + +#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return static_cast( x >> 32 ) != 0? + boost::core::detail::countl_impl( static_cast( x >> 32 ) ): + boost::core::detail::countl_impl( static_cast( x ) ) + 32; +} + +#else + +inline int countl_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return static_cast( x >> 32 ) != 0? + boost::core::detail::countl_impl( static_cast( x >> 32 ) ): + boost::core::detail::countl_impl( static_cast( x ) ) + 32; +} + +#endif + } // namespace detail template -int countl_zero( T x ) BOOST_NOEXCEPT +BOOST_CXX14_CONSTEXPR int countl_zero( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); @@ -250,10 +368,44 @@ BOOST_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT namespace detail { +#if defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + constexpr unsigned char mod37[ 37 ] = { 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 }; + return mod37[ ( -(boost::int32_t)x & x ) % 37 ]; + } + else + { + unsigned long r; + + if( _BitScanForward( &r, x ) ) + { + return static_cast( r ); + } + else + { + return 32; + } + } +} + +BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countr_impl( static_cast( x ) | 0x100 ); +} + +BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countr_impl( static_cast( x ) | 0x10000 ); +} + +#elif defined(_MSC_VER) + inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT { -#if defined(_MSC_VER) - unsigned long r; if( _BitScanForward( &r, x ) ) @@ -264,37 +416,6 @@ inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT { return 32; } - -#else - - static unsigned char const mod37[ 37 ] = { 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 }; - return mod37[ ( -(boost::int32_t)x & x ) % 37 ]; - -#endif -} - -inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT -{ -#if defined(_MSC_VER) && defined(_M_X64) - - unsigned long r; - - if( _BitScanForward64( &r, x ) ) - { - return static_cast( r ); - } - else - { - return 64; - } - -#else - - return static_cast( x ) != 0? - boost::core::detail::countr_impl( static_cast( x ) ): - boost::core::detail::countr_impl( static_cast( x >> 32 ) ) + 32; - -#endif } inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT @@ -307,10 +428,91 @@ inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT return boost::core::detail::countr_impl( static_cast( x ) | 0x10000 ); } +#else + +inline int countr_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + static unsigned char const mod37[ 37 ] = { 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 }; + return mod37[ ( -(boost::int32_t)x & x ) % 37 ]; +} + +inline int countr_impl( boost::uint8_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countr_impl( static_cast( x ) | 0x100 ); +} + +inline int countr_impl( boost::uint16_t x ) BOOST_NOEXCEPT +{ + return boost::core::detail::countr_impl( static_cast( x ) | 0x10000 ); +} + +#endif + +#if defined(_MSC_VER) && defined(_M_X64) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + return static_cast( x ) != 0? + boost::core::detail::countr_impl( static_cast( x ) ): + boost::core::detail::countr_impl( static_cast( x >> 32 ) ) + 32; + } + else + { + unsigned long r; + + if( _BitScanForward64( &r, x ) ) + { + return static_cast( r ); + } + else + { + return 64; + } + } +} + +#elif defined(_MSC_VER) && defined(_M_X64) + +inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + unsigned long r; + + if( _BitScanForward64( &r, x ) ) + { + return static_cast( r ); + } + else + { + return 64; + } +} + +#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return static_cast( x ) != 0? + boost::core::detail::countr_impl( static_cast( x ) ): + boost::core::detail::countr_impl( static_cast( x >> 32 ) ) + 32; +} + +#else + +inline int countr_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return static_cast( x ) != 0? + boost::core::detail::countr_impl( static_cast( x ) ): + boost::core::detail::countr_impl( static_cast( x >> 32 ) ) + 32; +} + +#endif + } // namespace detail template -int countr_zero( T x ) BOOST_NOEXCEPT +BOOST_CXX14_CONSTEXPR int countr_zero( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); @@ -446,7 +648,7 @@ BOOST_CXX14_CONSTEXPR T rotl( T x, int s ) BOOST_NOEXCEPT BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); unsigned const mask = std::numeric_limits::digits - 1; - return x << (s & mask) | x >> ((-s) & mask); + return static_cast( x << (static_cast( s ) & mask) | x >> (static_cast( -s ) & mask) ); } template @@ -455,7 +657,7 @@ BOOST_CXX14_CONSTEXPR T rotr( T x, int s ) BOOST_NOEXCEPT BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); unsigned const mask = std::numeric_limits::digits - 1; - return x >> (s & mask) | x << ((-s) & mask); + return static_cast( x >> (static_cast( s ) & mask) | x << (static_cast( -s ) & mask) ); } // integral powers of 2 @@ -484,7 +686,7 @@ BOOST_CONSTEXPR T bit_floor( T x ) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT( std::numeric_limits::is_integer && !std::numeric_limits::is_signed ); - return x == 0? 0: T(1) << ( boost::core::bit_width( x ) - 1 ); + return x == 0? T(0): static_cast( T(1) << ( boost::core::bit_width( x ) - 1 ) ); } namespace detail @@ -613,6 +815,117 @@ typedef endian::type endian_type; #undef BOOST_CORE_BIT_NATIVE_INITIALIZER +// byteswap + +namespace detail +{ + +BOOST_CONSTEXPR inline boost::uint8_t byteswap_impl( boost::uint8_t x ) BOOST_NOEXCEPT +{ + return x; +} + +BOOST_CONSTEXPR inline boost::uint16_t byteswap_impl( boost::uint16_t x ) BOOST_NOEXCEPT +{ + return static_cast( x << 8 | x >> 8 ); +} + +#if defined(__GNUC__) || defined(__clang__) + +BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + return __builtin_bswap32( x ); +} + +BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return __builtin_bswap64( x ); +} + +#elif defined(_MSC_VER) && defined(BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL) + +BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + boost::uint32_t step16 = x << 16 | x >> 16; + return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff); + } + else + { + return _byteswap_ulong( x ); + } +} + +BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + if( __builtin_is_constant_evaluated() ) + { + boost::uint64_t step32 = x << 32 | x >> 32; + boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16; + return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8; + } + else + { + return _byteswap_uint64( x ); + } +} + +#elif defined(_MSC_VER) + +inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + return _byteswap_ulong( x ); +} + +inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + return _byteswap_uint64( x ); +} + +#else + +BOOST_CXX14_CONSTEXPR inline boost::uint32_t byteswap_impl( boost::uint32_t x ) BOOST_NOEXCEPT +{ + boost::uint32_t step16 = x << 16 | x >> 16; + return ((step16 << 8) & 0xff00ff00) | ((step16 >> 8) & 0x00ff00ff); +} + +BOOST_CXX14_CONSTEXPR inline boost::uint64_t byteswap_impl( boost::uint64_t x ) BOOST_NOEXCEPT +{ + boost::uint64_t step32 = x << 32 | x >> 32; + boost::uint64_t step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 | (step32 & 0xFFFF0000FFFF0000ULL) >> 16; + return (step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8; +} + +#endif + +} // namespace detail + +template BOOST_CXX14_CONSTEXPR T byteswap( T x ) BOOST_NOEXCEPT +{ + BOOST_STATIC_ASSERT( std::numeric_limits::is_integer ); + + BOOST_STATIC_ASSERT( sizeof(T) == sizeof(boost::uint8_t) || sizeof(T) == sizeof(boost::uint16_t) || sizeof(T) == sizeof(boost::uint32_t) || sizeof(T) == sizeof(boost::uint64_t) ); + + BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint8_t) ) + { + return static_cast( boost::core::detail::byteswap_impl( static_cast( x ) ) ); + } + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint16_t) ) + { + return static_cast( boost::core::detail::byteswap_impl( static_cast( x ) ) ); + } + else BOOST_IF_CONSTEXPR ( sizeof(T) == sizeof(boost::uint32_t) ) + { + return static_cast( boost::core::detail::byteswap_impl( static_cast( x ) ) ); + } + else + { + return static_cast( boost::core::detail::byteswap_impl( static_cast( x ) ) ); + } +} + } // namespace core } // namespace boost diff --git a/boost/core/checked_delete.hpp b/boost/core/checked_delete.hpp index 6af5c14..b74a43a 100644 --- a/boost/core/checked_delete.hpp +++ b/boost/core/checked_delete.hpp @@ -30,16 +30,33 @@ namespace boost template inline void checked_delete(T * x) BOOST_NOEXCEPT { - // intentionally complex - simplification causes regressions - typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; +#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410L + + static_assert( sizeof(T) != 0, "Type must be complete" ); + +#else + + typedef char type_must_be_complete[ sizeof(T) ]; (void) sizeof(type_must_be_complete); + +#endif + delete x; } template inline void checked_array_delete(T * x) BOOST_NOEXCEPT { - typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; +#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410L + + static_assert( sizeof(T) != 0, "Type must be complete" ); + +#else + + typedef char type_must_be_complete[ sizeof(T) ]; (void) sizeof(type_must_be_complete); + +#endif + delete [] x; } diff --git a/boost/core/cmath.hpp b/boost/core/cmath.hpp deleted file mode 100644 index a18c81b..0000000 --- a/boost/core/cmath.hpp +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef BOOST_CORE_CMATH_HPP_INCLUDED -#define BOOST_CORE_CMATH_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// boost/core/cmath.hpp -// -// Floating point classification and sign manipulation functions -// Extracted from https://github.com/boostorg/lexical_cast/pull/37 -// -// Copyright 2020, 2021 Peter Dimov -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#include - -#if defined(BOOST_CORE_USE_GENERIC_CMATH) || (!defined(_MSC_VER) && !defined(FP_SUBNORMAL)) - -#include -#include -#include -#include - -namespace boost -{ -namespace core -{ - -// fpclassify return values - -int const fp_zero = 0; -int const fp_subnormal = 1; -int const fp_normal = 2; -int const fp_infinite = 3; -int const fp_nan = 4; - -// Classification functions - -template bool isfinite( T x ) -{ - return x <= (std::numeric_limits::max)() && x >= -(std::numeric_limits::max)(); -} - -template bool isinf( T x ) -{ - return x > (std::numeric_limits::max)() || x < -(std::numeric_limits::max)(); -} - -template bool isnan( T x ) -{ - return !isfinite( x ) && !isinf( x ); -} - -template bool isnormal( T x ) -{ - return isfinite( x ) && ( x >= (std::numeric_limits::min)() || x <= -(std::numeric_limits::min)() ); -} - -template int fpclassify( T x ) -{ - if( x == 0 ) return fp_zero; - - if( x < 0 ) x = -x; - - if( x > (std::numeric_limits::max)() ) return fp_infinite; - - if( x >= (std::numeric_limits::min)() ) return fp_normal; - - if( x < (std::numeric_limits::min)() ) return fp_subnormal; - - return fp_nan; -} - -// Sign manipulation functions - -inline bool signbit( float x ) -{ - boost::int32_t y; - - BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) ); - - std::memcpy( &y, &x, sizeof( y ) ); - - return y < 0; -} - -inline bool signbit( double x ) -{ - boost::int64_t y; - - BOOST_STATIC_ASSERT( sizeof( x ) == sizeof( y ) ); - - std::memcpy( &y, &x, sizeof( y ) ); - - return y < 0; -} - -inline bool signbit( long double x ) -{ - return signbit( static_cast( x ) ); -} - -template T copysign( T x, T y ) -{ - return signbit( x ) == signbit( y )? x: -x; -} - -} // namespace core -} // namespace boost - -#else // defined(BOOST_CORE_USE_GENERIC_CMATH) - -#if defined(_MSC_VER) && _MSC_VER < 1800 -# include -#endif - -namespace boost -{ -namespace core -{ -#if defined(_MSC_VER) && _MSC_VER < 1800 - -template T copysign( T x, T y ) -{ - return static_cast( _copysign( static_cast( x ), static_cast( y ) ) ); -} - -template bool isnan( T x ) -{ - return _isnan( static_cast( x ) ) != 0; -} - -template bool isfinite( T x ) -{ - return _finite( static_cast( x ) ) != 0; -} - -template bool isinf( T x ) -{ - return ( _fpclass( static_cast( x ) ) & ( _FPCLASS_PINF | _FPCLASS_NINF ) ) != 0; -} - -inline bool isnormal( float x ) -{ - // no _fpclassf in 32 bit mode - unsigned y = reinterpret_cast< unsigned const& >( x ); - unsigned exp = ( y >> 23 ) & 0xFF; - return exp != 0 && exp != 0xFF; -} - -inline bool isnormal( double x ) -{ - return ( _fpclass( x ) & ( _FPCLASS_PN | _FPCLASS_NN ) ) != 0; -} - -inline bool isnormal( long double x ) -{ - return boost::core::isnormal( static_cast( x ) ); -} - -template bool signbit( T x ) -{ - return _copysign( 1.0, static_cast( x ) ) < 0.0; -} - -int const fp_zero = 0; -int const fp_subnormal = 1; -int const fp_normal = 2; -int const fp_infinite = 3; -int const fp_nan = 4; - -inline int fpclassify( float x ) -{ - switch( _fpclass( x ) ) - { - case _FPCLASS_SNAN: - case _FPCLASS_QNAN: - - return fp_nan; - - case _FPCLASS_NINF: - case _FPCLASS_PINF: - - return fp_infinite; - - case _FPCLASS_NZ: - case _FPCLASS_PZ: - - return fp_zero; - - default: - - return boost::core::isnormal( x )? fp_normal: fp_subnormal; - } -} - -inline int fpclassify( double x ) -{ - switch( _fpclass( x ) ) - { - case _FPCLASS_SNAN: - case _FPCLASS_QNAN: - - return fp_nan; - - case _FPCLASS_NINF: - case _FPCLASS_PINF: - - return fp_infinite; - - case _FPCLASS_NZ: - case _FPCLASS_PZ: - - return fp_zero; - - case _FPCLASS_ND: - case _FPCLASS_PD: - - return fp_subnormal; - - default: - - return fp_normal; - } -} - -inline int fpclassify( long double x ) -{ - return boost::core::fpclassify( static_cast( x ) ); -} - -#else - -using std::isfinite; -using std::isnan; -using std::isinf; -using std::isnormal; -using std::fpclassify; - -int const fp_zero = FP_ZERO; -int const fp_subnormal = FP_SUBNORMAL; -int const fp_normal = FP_NORMAL; -int const fp_infinite = FP_INFINITE; -int const fp_nan = FP_NAN; - -using std::signbit; - -// std::copysign doesn't exist in libstdc++ under -std=c++03 - -#if !defined(__GNUC__) - -template T copysign( T x, T y ) -{ - return std::copysign( x, y ); -} - -#else - -namespace detail -{ - -// ::copysignl is unreliable, use the built-ins - -inline float copysign_impl( float x, float y ) -{ - return __builtin_copysignf( x, y ); -} - -inline double copysign_impl( double x, double y ) -{ - return __builtin_copysign( x, y ); -} - -inline long double copysign_impl( long double x, long double y ) -{ - return __builtin_copysignl( x, y ); -} - -} // namespace detail - -template T copysign( T x, T y ) -{ - return boost::core::detail::copysign_impl( x, y ); -} - -#endif // !defined(__GNUC__) -#endif // #if defined(_MSC_VER) && _MSC_VER < 1800 - -} // namespace core -} // namespace boost - -#endif // defined(BOOST_CORE_USE_GENERIC_CMATH) - -#endif // #ifndef BOOST_CORE_CMATH_HPP_INCLUDED diff --git a/boost/core/detail/sp_thread_pause.hpp b/boost/core/detail/sp_thread_pause.hpp new file mode 100644 index 0000000..01be1a0 --- /dev/null +++ b/boost/core/detail/sp_thread_pause.hpp @@ -0,0 +1,71 @@ +#ifndef BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED +#define BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// boost/core/detail/sp_thread_pause.hpp +// +// inline void bost::core::sp_thread_pause(); +// +// Emits a "pause" instruction. +// +// Copyright 2008, 2020, 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0 +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(__has_builtin) +# if __has_builtin(__builtin_ia32_pause) && !defined(_INTEL_COMPILER) +# define BOOST_CORE_HAS_BUILTIN_IA32_PAUSE +# endif +#endif + +#if defined(BOOST_CORE_HAS_BUILTIN_IA32_PAUSE) + +# define BOOST_CORE_SP_PAUSE() __builtin_ia32_pause() + +#elif defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) ) + +# include +# define BOOST_CORE_SP_PAUSE() _mm_pause() + +#elif defined(_MSC_VER) && ( defined(_M_ARM) || defined(_M_ARM64) ) + +# include +# define BOOST_CORE_SP_PAUSE() __yield() + +#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) + +# define BOOST_CORE_SP_PAUSE() __asm__ __volatile__( "rep; nop" : : : "memory" ) + +#elif defined(__GNUC__) && ( (defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__) || defined(__aarch64__) ) + +# define BOOST_CORE_SP_PAUSE() __asm__ __volatile__( "yield" : : : "memory" ) + +#else + +# define BOOST_CORE_SP_PAUSE() ((void)0) + +#endif + +namespace boost +{ +namespace core +{ + +BOOST_FORCEINLINE void sp_thread_pause() BOOST_NOEXCEPT +{ + BOOST_CORE_SP_PAUSE(); +} + +} // namespace core +} // namespace boost + +#undef BOOST_CORE_SP_PAUSE + +#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/sp_thread_sleep.hpp b/boost/core/detail/sp_thread_sleep.hpp similarity index 54% rename from boost/smart_ptr/detail/sp_thread_sleep.hpp rename to boost/core/detail/sp_thread_sleep.hpp index ff1d168..f461c3f 100644 --- a/boost/smart_ptr/detail/sp_thread_sleep.hpp +++ b/boost/core/detail/sp_thread_sleep.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED +#ifndef BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED +#define BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -7,41 +7,45 @@ # pragma once #endif -// boost/smart_ptr/detail/sp_thread_sleep.hpp +// boost/core/detail/sp_thread_sleep.hpp // -// inline void bost::detail::sp_thread_sleep(); +// inline void bost::core::sp_thread_sleep(); // // Cease execution for a while to yield to other threads, // as if by calling nanosleep() with an appropriate interval. // -// Copyright 2008, 2020 Peter Dimov +// Copyright 2008, 2020, 2023 Peter Dimov // Distributed under the Boost Software License, Version 1.0 // https://www.boost.org/LICENSE_1_0.txt #include #include -#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) +#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) #if defined(BOOST_SP_REPORT_IMPLEMENTATION) BOOST_PRAGMA_MESSAGE("Using Sleep(1) in sp_thread_sleep") #endif -#include +#include namespace boost { - +namespace core +{ namespace detail { -inline void sp_thread_sleep() +inline void sp_thread_sleep() BOOST_NOEXCEPT { Sleep( 1 ); } } // namespace detail +using boost::core::detail::sp_thread_sleep; + +} // namespace core } // namespace boost #elif defined(BOOST_HAS_NANOSLEEP) @@ -52,14 +56,24 @@ inline void sp_thread_sleep() #include +#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__) +# include +#endif + namespace boost { - -namespace detail +namespace core { -inline void sp_thread_sleep() +inline void sp_thread_sleep() BOOST_NOEXCEPT { +#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__) + + int oldst; + pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldst ); + +#endif + // g++ -Wextra warns on {} or {0} struct timespec rqtp = { 0, 0 }; @@ -70,10 +84,16 @@ inline void sp_thread_sleep() rqtp.tv_nsec = 1000; nanosleep( &rqtp, 0 ); + +#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__) + + pthread_setcancelstate( oldst, &oldst ); + +#endif + } -} // namespace detail - +} // namespace core } // namespace boost #else @@ -82,23 +102,21 @@ inline void sp_thread_sleep() BOOST_PRAGMA_MESSAGE("Using sp_thread_yield() in sp_thread_sleep") #endif -#include +#include namespace boost { - -namespace detail +namespace core { -inline void sp_thread_sleep() +inline void sp_thread_sleep() BOOST_NOEXCEPT { sp_thread_yield(); } -} // namespace detail - +} // namespace core } // namespace boost #endif -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED +#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/sp_thread_yield.hpp b/boost/core/detail/sp_thread_yield.hpp similarity index 58% rename from boost/smart_ptr/detail/sp_thread_yield.hpp rename to boost/core/detail/sp_thread_yield.hpp index 9a221cc..25127e8 100644 --- a/boost/smart_ptr/detail/sp_thread_yield.hpp +++ b/boost/core/detail/sp_thread_yield.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED +#ifndef BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED +#define BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -7,9 +7,9 @@ # pragma once #endif -// boost/smart_ptr/detail/sp_thread_yield.hpp +// boost/core/detail/sp_thread_yield.hpp // -// inline void bost::detail::sp_thread_yield(); +// inline void bost::core::sp_thread_yield(); // // Gives up the remainder of the time slice, // as if by calling sched_yield(). @@ -21,27 +21,31 @@ #include #include -#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) +#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) #if defined(BOOST_SP_REPORT_IMPLEMENTATION) - BOOST_PRAGMA_MESSAGE("Using Sleep(0) in sp_thread_yield") + BOOST_PRAGMA_MESSAGE("Using SwitchToThread() in sp_thread_yield") #endif -#include +#include namespace boost { - +namespace core +{ namespace detail { -inline void sp_thread_yield() +inline void sp_thread_yield() BOOST_NOEXCEPT { - Sleep( 0 ); + SwitchToThread(); } } // namespace detail +using boost::core::detail::sp_thread_yield; + +} // namespace core } // namespace boost #elif defined(BOOST_HAS_SCHED_YIELD) @@ -59,17 +63,15 @@ inline void sp_thread_yield() namespace boost { - -namespace detail +namespace core { -inline void sp_thread_yield() +inline void sp_thread_yield() BOOST_NOEXCEPT { sched_yield(); } -} // namespace detail - +} // namespace core } // namespace boost #else @@ -78,23 +80,21 @@ inline void sp_thread_yield() BOOST_PRAGMA_MESSAGE("Using sp_thread_pause() in sp_thread_yield") #endif -#include +#include namespace boost { - -namespace detail +namespace core { -inline void sp_thread_yield() +inline void sp_thread_yield() BOOST_NOEXCEPT { sp_thread_pause(); } -} // namespace detail - +} // namespace core } // namespace boost #endif -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED +#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/sp_win32_sleep.hpp b/boost/core/detail/sp_win32_sleep.hpp similarity index 53% rename from boost/smart_ptr/detail/sp_win32_sleep.hpp rename to boost/core/detail/sp_win32_sleep.hpp index 139a569..adec53e 100644 --- a/boost/smart_ptr/detail/sp_win32_sleep.hpp +++ b/boost/core/detail/sp_win32_sleep.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED +#ifndef BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED +#define BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED // MS compatible compilers support #pragma once @@ -7,7 +7,7 @@ # pragma once #endif -// boost/smart_ptr/detail/sp_win32_sleep.hpp +// boost/core/detail/sp_win32_sleep.hpp // // Declares the Win32 Sleep() function. // @@ -21,6 +21,8 @@ namespace boost { +namespace core +{ namespace detail { @@ -28,22 +30,25 @@ namespace detail #if defined(__clang__) && defined(__x86_64__) // clang x64 warns that __stdcall is ignored -# define BOOST_SP_STDCALL +# define BOOST_CORE_SP_STDCALL #else -# define BOOST_SP_STDCALL __stdcall +# define BOOST_CORE_SP_STDCALL __stdcall #endif #if defined(__LP64__) // Cygwin 64 - extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms ); + extern "C" __declspec(dllimport) void BOOST_CORE_SP_STDCALL Sleep( unsigned int ms ); #else - extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms ); + extern "C" __declspec(dllimport) void BOOST_CORE_SP_STDCALL Sleep( unsigned long ms ); #endif -#undef BOOST_SP_STDCALL +extern "C" __declspec(dllimport) int BOOST_CORE_SP_STDCALL SwitchToThread(); + +#undef BOOST_CORE_SP_STDCALL #endif // !defined( BOOST_USE_WINDOWS_H ) } // namespace detail +} // namespace core } // namespace boost -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED +#endif // #ifndef BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED diff --git a/boost/core/scoped_enum.hpp b/boost/core/scoped_enum.hpp new file mode 100644 index 0000000..56dd0ed --- /dev/null +++ b/boost/core/scoped_enum.hpp @@ -0,0 +1,194 @@ +// scoped_enum.hpp ---------------------------------------------------------// + +// Copyright Beman Dawes, 2009 +// Copyright (C) 2011-2012 Vicente J. Botet Escriba +// Copyright (C) 2012 Anthony Williams + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_CORE_SCOPED_ENUM_HPP +#define BOOST_CORE_SCOPED_ENUM_HPP + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost +{ + +#ifdef BOOST_NO_CXX11_SCOPED_ENUMS + + /** + * Meta-function to get the native enum type associated to an enum class or its emulation. + */ + template + struct native_type + { + /** + * The member typedef type names the native enum type associated to the scoped enum, + * which is it self if the compiler supports scoped enums or EnumType::enum_type if it is an emulated scoped enum. + */ + typedef typename EnumType::enum_type type; + }; + + /** + * Casts a scoped enum to its underlying type. + * + * This function is useful when working with scoped enum classes, which doens't implicitly convert to the underlying type. + * @param v A scoped enum. + * @returns The underlying type. + * @throws No-throws. + */ + template + inline + BOOST_CONSTEXPR UnderlyingType underlying_cast(EnumType v) BOOST_NOEXCEPT + { + return v.get_underlying_value_(); + } + + /** + * Casts a scoped enum to its native enum type. + * + * This function is useful to make programs portable when the scoped enum emulation can not be use where native enums can. + * + * EnumType the scoped enum type + * + * @param v A scoped enum. + * @returns The native enum value. + * @throws No-throws. + */ + template + inline + BOOST_CONSTEXPR typename EnumType::enum_type native_value(EnumType e) BOOST_NOEXCEPT + { + return e.get_native_value_(); + } + +#else // BOOST_NO_CXX11_SCOPED_ENUMS + + template + struct native_type + { + typedef EnumType type; + }; + + template + inline + BOOST_CONSTEXPR UnderlyingType underlying_cast(EnumType v) BOOST_NOEXCEPT + { + return static_cast(v); + } + + template + inline + BOOST_CONSTEXPR EnumType native_value(EnumType e) BOOST_NOEXCEPT + { + return e; + } + +#endif // BOOST_NO_CXX11_SCOPED_ENUMS +} + + +#ifdef BOOST_NO_CXX11_SCOPED_ENUMS + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + +#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \ + explicit BOOST_CONSTEXPR operator underlying_type() const BOOST_NOEXCEPT { return get_underlying_value_(); } + +#else + +#define BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR + +#endif + +/** + * Start a declaration of a scoped enum. + * + * @param EnumType The new scoped enum. + * @param UnderlyingType The underlying type. + */ +#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType, UnderlyingType) \ + struct EnumType { \ + typedef void is_boost_scoped_enum_tag; \ + typedef UnderlyingType underlying_type; \ + EnumType() BOOST_NOEXCEPT {} \ + explicit BOOST_CONSTEXPR EnumType(underlying_type v) BOOST_NOEXCEPT : v_(v) {} \ + BOOST_CONSTEXPR underlying_type get_underlying_value_() const BOOST_NOEXCEPT { return v_; } \ + BOOST_SCOPED_ENUM_UT_DECLARE_CONVERSION_OPERATOR \ + private: \ + underlying_type v_; \ + typedef EnumType self_type; \ + public: \ + enum enum_type + +#define BOOST_SCOPED_ENUM_DECLARE_END2() \ + BOOST_CONSTEXPR enum_type get_native_value_() const BOOST_NOEXCEPT { return enum_type(v_); } \ + friend BOOST_CONSTEXPR bool operator ==(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator ==(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)==rhs; } \ + friend BOOST_CONSTEXPR bool operator ==(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs==enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator !=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator !=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)!=rhs; } \ + friend BOOST_CONSTEXPR bool operator !=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs!=enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator <(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator >(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>rhs; } \ + friend BOOST_CONSTEXPR bool operator >(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator >=(self_type lhs, self_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=enum_type(rhs.v_); } \ + friend BOOST_CONSTEXPR bool operator >=(self_type lhs, enum_type rhs) BOOST_NOEXCEPT { return enum_type(lhs.v_)>=rhs; } \ + friend BOOST_CONSTEXPR bool operator >=(enum_type lhs, self_type rhs) BOOST_NOEXCEPT { return lhs>=enum_type(rhs.v_); } \ + }; + +#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) \ + ; \ + BOOST_CONSTEXPR EnumType(enum_type v) BOOST_NOEXCEPT : v_(v) {} \ + BOOST_SCOPED_ENUM_DECLARE_END2() + +/** + * Starts a declaration of a scoped enum with the default int underlying type. + * + * @param EnumType The new scoped enum. + */ +#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(EnumType) \ + BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,int) + +/** + * Name of the native enum type. + * + * @param EnumType The new scoped enum. + */ +#define BOOST_SCOPED_ENUM_NATIVE(EnumType) EnumType::enum_type +/** + * Forward declares an scoped enum. + * + * @param EnumType The scoped enum. + */ +#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(EnumType) struct EnumType + +#else // BOOST_NO_CXX11_SCOPED_ENUMS + +#define BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(EnumType,UnderlyingType) enum class EnumType : UnderlyingType +#define BOOST_SCOPED_ENUM_DECLARE_BEGIN(EnumType) enum class EnumType +#define BOOST_SCOPED_ENUM_DECLARE_END2() +#define BOOST_SCOPED_ENUM_DECLARE_END(EnumType) ; + +#define BOOST_SCOPED_ENUM_NATIVE(EnumType) EnumType +#define BOOST_SCOPED_ENUM_FORWARD_DECLARE(EnumType) enum class EnumType + +#endif // BOOST_NO_CXX11_SCOPED_ENUMS + +// Deprecated macros +#define BOOST_SCOPED_ENUM_START(name) BOOST_SCOPED_ENUM_DECLARE_BEGIN(name) +#define BOOST_SCOPED_ENUM_END BOOST_SCOPED_ENUM_DECLARE_END2() +#define BOOST_SCOPED_ENUM(name) BOOST_SCOPED_ENUM_NATIVE(name) + +#endif // BOOST_CORE_SCOPED_ENUM_HPP diff --git a/boost/core/yield_primitives.hpp b/boost/core/yield_primitives.hpp new file mode 100644 index 0000000..899453e --- /dev/null +++ b/boost/core/yield_primitives.hpp @@ -0,0 +1,12 @@ +#ifndef BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED +#define BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +#endif // #ifndef BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED diff --git a/boost/date_time/date_facet.hpp b/boost/date_time/date_facet.hpp deleted file mode 100644 index 4ab4923..0000000 --- a/boost/date_time/date_facet.hpp +++ /dev/null @@ -1,766 +0,0 @@ -#ifndef _DATE_TIME_DATE_FACET__HPP___ -#define _DATE_TIME_DATE_FACET__HPP___ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Martin Andrian, Jeff Garland, Bart Garst - * $Date$ - */ - -#include // ostreambuf_iterator -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace date_time { - - - /*! Class that provides format based I/O facet for date types. - * - * This class allows the formatting of dates by using format string. - * Format strings are: - * - * - %A => long_weekday_format - Full name Ex: Tuesday - * - %a => short_weekday_format - Three letter abbreviation Ex: Tue - * - %B => long_month_format - Full name Ex: October - * - %b => short_month_format - Three letter abbreviation Ex: Oct - * - %x => standard_format_specifier - defined by the locale - * - %Y-%b-%d => default_date_format - YYYY-Mon-dd - * - * Default month format == %b - * Default weekday format == %a - */ - template > > - class BOOST_SYMBOL_VISIBLE date_facet : public std::locale::facet { - public: - typedef typename date_type::duration_type duration_type; - // greg_weekday is gregorian_calendar::day_of_week_type - typedef typename date_type::day_of_week_type day_of_week_type; - typedef typename date_type::day_type day_type; - typedef typename date_type::month_type month_type; - typedef boost::date_time::period period_type; - typedef std::basic_string string_type; - typedef CharT char_type; - typedef boost::date_time::period_formatter period_formatter_type; - typedef boost::date_time::special_values_formatter special_values_formatter_type; - typedef std::vector > input_collection_type; - // used for the output of the date_generators - typedef date_generator_formatter date_gen_formatter_type; - typedef partial_date partial_date_type; - typedef nth_kday_of_month nth_kday_type; - typedef first_kday_of_month first_kday_type; - typedef last_kday_of_month last_kday_type; - typedef first_kday_after kday_after_type; - typedef first_kday_before kday_before_type; - static const char_type long_weekday_format[3]; - static const char_type short_weekday_format[3]; - static const char_type long_month_format[3]; - static const char_type short_month_format[3]; - static const char_type default_period_separator[4]; - static const char_type standard_format_specifier[3]; - static const char_type iso_format_specifier[7]; - static const char_type iso_format_extended_specifier[9]; - static const char_type default_date_format[9]; // YYYY-Mon-DD - static std::locale::id id; - -#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) - std::locale::id& __get_id (void) const { return id; } -#endif - - explicit date_facet(::size_t a_ref = 0) - : std::locale::facet(a_ref), - //m_format(standard_format_specifier) - m_format(default_date_format), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format) - {} - - explicit date_facet(const char_type* format_str, - const input_collection_type& short_names, - ::size_t ref_count = 0) - : std::locale::facet(ref_count), - m_format(format_str), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format), - m_month_short_names(short_names) - {} - - - explicit date_facet(const char_type* format_str, - period_formatter_type per_formatter = period_formatter_type(), - special_values_formatter_type sv_formatter = special_values_formatter_type(), - date_gen_formatter_type dg_formatter = date_gen_formatter_type(), - ::size_t ref_count = 0) - : std::locale::facet(ref_count), - m_format(format_str), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format), - m_period_formatter(per_formatter), - m_date_gen_formatter(dg_formatter), - m_special_values_formatter(sv_formatter) - {} - void format(const char_type* const format_str) { - m_format = format_str; - } - virtual void set_iso_format() - { - m_format = iso_format_specifier; - } - virtual void set_iso_extended_format() - { - m_format = iso_format_extended_specifier; - } - void month_format(const char_type* const format_str) { - m_month_format = format_str; - } - void weekday_format(const char_type* const format_str) { - m_weekday_format = format_str; - } - - void period_formatter(period_formatter_type per_formatter) { - m_period_formatter= per_formatter; - } - void special_values_formatter(const special_values_formatter_type& svf) - { - m_special_values_formatter = svf; - } - void short_weekday_names(const input_collection_type& short_names) - { - m_weekday_short_names = short_names; - } - void long_weekday_names(const input_collection_type& long_names) - { - m_weekday_long_names = long_names; - } - - void short_month_names(const input_collection_type& short_names) - { - m_month_short_names = short_names; - } - - void long_month_names(const input_collection_type& long_names) - { - m_month_long_names = long_names; - } - - void date_gen_phrase_strings(const input_collection_type& new_strings, - typename date_gen_formatter_type::phrase_elements beg_pos=date_gen_formatter_type::first) - { - m_date_gen_formatter.elements(new_strings, beg_pos); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const date_type& d) const - { - if (d.is_special()) { - return do_put_special(next, a_ios, fill_char, d.as_special()); - } - //The following line of code required the date to support a to_tm function - return do_put_tm(next, a_ios, fill_char, to_tm(d), m_format); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const duration_type& dd) const - { - if (dd.is_special()) { - return do_put_special(next, a_ios, fill_char, dd.get_rep().as_special()); - } - - typedef std::num_put num_put; - if (std::has_facet(a_ios.getloc())) { - return std::use_facet(a_ios.getloc()).put(next, a_ios, fill_char, dd.get_rep().as_number()); - } - else { - num_put* f = new num_put(); - std::locale l = std::locale(a_ios.getloc(), f); - a_ios.imbue(l); - return f->put(next, a_ios, fill_char, dd.get_rep().as_number()); - } - - } - - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const month_type& m) const - { - //if (d.is_special()) { - // return do_put_special(next, a_ios, fill_char, d.as_special()); - //} - //The following line of code required the date to support a to_tm function - std::tm dtm; - std::memset(&dtm, 0, sizeof(dtm)); - dtm.tm_mon = m - 1; - return do_put_tm(next, a_ios, fill_char, dtm, m_month_format); - } - - //! puts the day of month - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const day_type& day) const - { - std::tm dtm; - std::memset(&dtm, 0, sizeof(dtm)); - dtm.tm_mday = day.as_number(); - char_type tmp[3] = {'%','d'}; - string_type temp_format(tmp); - return do_put_tm(next, a_ios, fill_char, dtm, temp_format); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const day_of_week_type& dow) const - { - //if (d.is_special()) { - // return do_put_special(next, a_ios, fill_char, d.as_special()); - //} - //The following line of code required the date to support a to_tm function - std::tm dtm; - std::memset(&dtm, 0, sizeof(dtm)); - dtm.tm_wday = dow; - return do_put_tm(next, a_ios, fill_char, dtm, m_weekday_format); - } - - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const period_type& p) const - { - return m_period_formatter.put_period(next, a_ios, fill_char, p, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const partial_date_type& pd) const - { - return m_date_gen_formatter.put_partial_date(next, a_ios, fill_char, pd, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const nth_kday_type& nkd) const - { - return m_date_gen_formatter.put_nth_kday(next, a_ios, fill_char, nkd, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const first_kday_type& fkd) const - { - return m_date_gen_formatter.put_first_kday(next, a_ios, fill_char, fkd, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const last_kday_type& lkd) const - { - return m_date_gen_formatter.put_last_kday(next, a_ios, fill_char, lkd, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const kday_before_type& fkb) const - { - return m_date_gen_formatter.put_kday_before(next, a_ios, fill_char, fkb, *this); - } - - OutItrT put(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const kday_after_type& fka) const - { - return m_date_gen_formatter.put_kday_after(next, a_ios, fill_char, fka, *this); - } - - protected: - virtual OutItrT do_put_special(OutItrT next, - std::ios_base& /*a_ios*/, - char_type /*fill_char*/, - const boost::date_time::special_values sv) const - { - m_special_values_formatter.put_special(next, sv); - return next; - } - virtual OutItrT do_put_tm(OutItrT next, - std::ios_base& a_ios, - char_type fill_char, - const tm& tm_value, - string_type a_format) const - { - // update format string with custom names - if (!m_weekday_long_names.empty()) { - boost::algorithm::replace_all(a_format, - long_weekday_format, - m_weekday_long_names[tm_value.tm_wday]); - } - if (!m_weekday_short_names.empty()) { - boost::algorithm::replace_all(a_format, - short_weekday_format, - m_weekday_short_names[tm_value.tm_wday]); - - } - if (!m_month_long_names.empty()) { - boost::algorithm::replace_all(a_format, - long_month_format, - m_month_long_names[tm_value.tm_mon]); - } - if (!m_month_short_names.empty()) { - boost::algorithm::replace_all(a_format, - short_month_format, - m_month_short_names[tm_value.tm_mon]); - } - // use time_put facet to create final string - const char_type* p_format = a_format.c_str(); - return std::use_facet >(a_ios.getloc()).put(next, a_ios, - fill_char, - &tm_value, - p_format, - p_format + a_format.size()); - } - protected: - string_type m_format; - string_type m_month_format; - string_type m_weekday_format; - period_formatter_type m_period_formatter; - date_gen_formatter_type m_date_gen_formatter; - special_values_formatter_type m_special_values_formatter; - input_collection_type m_month_short_names; - input_collection_type m_month_long_names; - input_collection_type m_weekday_short_names; - input_collection_type m_weekday_long_names; - private: - }; - - template - std::locale::id date_facet::id; - - template - const typename date_facet::char_type - date_facet::long_weekday_format[3] = {'%','A'}; - - template - const typename date_facet::char_type - date_facet::short_weekday_format[3] = {'%','a'}; - - template - const typename date_facet::char_type - date_facet::long_month_format[3] = {'%','B'}; - - template - const typename date_facet::char_type - date_facet::short_month_format[3] = {'%','b'}; - - template - const typename date_facet::char_type - date_facet::default_period_separator[4] = { ' ', '/', ' '}; - - template - const typename date_facet::char_type - date_facet::standard_format_specifier[3] = - {'%', 'x' }; - - template - const typename date_facet::char_type - date_facet::iso_format_specifier[7] = - {'%', 'Y', '%', 'm', '%', 'd' }; - - template - const typename date_facet::char_type - date_facet::iso_format_extended_specifier[9] = - {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; - - template - const typename date_facet::char_type - date_facet::default_date_format[9] = - {'%','Y','-','%','b','-','%','d'}; - - - - //! Input facet - template > > - class BOOST_SYMBOL_VISIBLE date_input_facet : public std::locale::facet { - public: - typedef typename date_type::duration_type duration_type; - // greg_weekday is gregorian_calendar::day_of_week_type - typedef typename date_type::day_of_week_type day_of_week_type; - typedef typename date_type::day_type day_type; - typedef typename date_type::month_type month_type; - typedef typename date_type::year_type year_type; - typedef boost::date_time::period period_type; - typedef std::basic_string string_type; - typedef CharT char_type; - typedef boost::date_time::period_parser period_parser_type; - typedef boost::date_time::special_values_parser special_values_parser_type; - typedef std::vector > input_collection_type; - typedef format_date_parser format_date_parser_type; - // date_generators stuff goes here - typedef date_generator_parser date_gen_parser_type; - typedef partial_date partial_date_type; - typedef nth_kday_of_month nth_kday_type; - typedef first_kday_of_month first_kday_type; - typedef last_kday_of_month last_kday_type; - typedef first_kday_after kday_after_type; - typedef first_kday_before kday_before_type; - - static const char_type long_weekday_format[3]; - static const char_type short_weekday_format[3]; - static const char_type long_month_format[3]; - static const char_type short_month_format[3]; - static const char_type four_digit_year_format[3]; - static const char_type two_digit_year_format[3]; - static const char_type default_period_separator[4]; - static const char_type standard_format_specifier[3]; - static const char_type iso_format_specifier[7]; - static const char_type iso_format_extended_specifier[9]; - static const char_type default_date_format[9]; // YYYY-Mon-DD - static std::locale::id id; - - explicit date_input_facet(::size_t a_ref = 0) - : std::locale::facet(a_ref), - m_format(default_date_format), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format), - m_year_format(four_digit_year_format), - m_parser(m_format, std::locale::classic()) - // default period_parser & special_values_parser used - {} - - explicit date_input_facet(const string_type& format_str, - ::size_t a_ref = 0) - : std::locale::facet(a_ref), - m_format(format_str), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format), - m_year_format(four_digit_year_format), - m_parser(m_format, std::locale::classic()) - // default period_parser & special_values_parser used - {} - - explicit date_input_facet(const string_type& format_str, - const format_date_parser_type& date_parser, - const special_values_parser_type& sv_parser, - const period_parser_type& per_parser, - const date_gen_parser_type& date_gen_parser, - ::size_t ref_count = 0) - : std::locale::facet(ref_count), - m_format(format_str), - m_month_format(short_month_format), - m_weekday_format(short_weekday_format), - m_year_format(four_digit_year_format), - m_parser(date_parser), - m_date_gen_parser(date_gen_parser), - m_period_parser(per_parser), - m_sv_parser(sv_parser) - {} - - - void format(const char_type* const format_str) { - m_format = format_str; - } - virtual void set_iso_format() - { - m_format = iso_format_specifier; - } - virtual void set_iso_extended_format() - { - m_format = iso_format_extended_specifier; - } - void month_format(const char_type* const format_str) { - m_month_format = format_str; - } - void weekday_format(const char_type* const format_str) { - m_weekday_format = format_str; - } - void year_format(const char_type* const format_str) { - m_year_format = format_str; - } - - void period_parser(period_parser_type per_parser) { - m_period_parser = per_parser; - } - void short_weekday_names(const input_collection_type& weekday_names) - { - m_parser.short_weekday_names(weekday_names); - } - void long_weekday_names(const input_collection_type& weekday_names) - { - m_parser.long_weekday_names(weekday_names); - } - - void short_month_names(const input_collection_type& month_names) - { - m_parser.short_month_names(month_names); - } - - void long_month_names(const input_collection_type& month_names) - { - m_parser.long_month_names(month_names); - } - - void date_gen_element_strings(const input_collection_type& col) - { - m_date_gen_parser.element_strings(col); - } - void date_gen_element_strings(const string_type& first, - const string_type& second, - const string_type& third, - const string_type& fourth, - const string_type& fifth, - const string_type& last, - const string_type& before, - const string_type& after, - const string_type& of) - - { - m_date_gen_parser.element_strings(first,second,third,fourth,fifth,last,before,after,of); - } - - void special_values_parser(special_values_parser_type sv_parser) - { - m_sv_parser = sv_parser; - } - - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& /*a_ios*/, - date_type& d) const - { - d = m_parser.parse_date(from, to, m_format, m_sv_parser); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& /*a_ios*/, - month_type& m) const - { - m = m_parser.parse_month(from, to, m_month_format); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& /*a_ios*/, - day_of_week_type& wd) const - { - wd = m_parser.parse_weekday(from, to, m_weekday_format); - return from; - } - //! Expects 1 or 2 digit day range: 1-31 - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& /*a_ios*/, - day_type& d) const - { - d = m_parser.parse_var_day_of_month(from, to); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& /*a_ios*/, - year_type& y) const - { - y = m_parser.parse_year(from, to, m_year_format); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - duration_type& dd) const - { - // skip leading whitespace - while(std::isspace(*from) && from != to) { ++from; } - - /* num_get.get() will always consume the first character if it - * is a sign indicator (+/-). Special value strings may begin - * with one of these signs so we'll need a copy of it - * in case num_get.get() fails. */ - char_type c = '\0'; - // TODO Are these characters somewhere in the locale? - if(*from == '-' || *from == '+') { - c = *from; - } - typedef std::num_get num_get; - typename duration_type::duration_rep_type val = 0; - std::ios_base::iostate err = std::ios_base::goodbit; - - if (std::has_facet(a_ios.getloc())) { - from = std::use_facet(a_ios.getloc()).get(from, to, a_ios, err, val); - } - else { - num_get* ng = new num_get(); - std::locale l = std::locale(a_ios.getloc(), ng); - a_ios.imbue(l); - from = ng->get(from, to, a_ios, err, val); - } - if(err & std::ios_base::failbit){ - typedef typename special_values_parser_type::match_results match_results; - match_results mr; - if(c == '-' || c == '+') { // was the first character consumed? - mr.cache += c; - } - m_sv_parser.match(from, to, mr); - if(mr.current_match == match_results::PARSE_ERROR) { - boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); - BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return from); // should never reach - } - dd = duration_type(static_cast(mr.current_match)); - } - else { - dd = duration_type(val); - } - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - period_type& p) const - { - p = m_period_parser.get_period(from, to, a_ios, p, duration_type::unit(), *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - nth_kday_type& nkd) const - { - nkd = m_date_gen_parser.get_nth_kday_type(from, to, a_ios, *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - partial_date_type& pd) const - { - - pd = m_date_gen_parser.get_partial_date_type(from, to, a_ios, *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - first_kday_type& fkd) const - { - fkd = m_date_gen_parser.get_first_kday_type(from, to, a_ios, *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - last_kday_type& lkd) const - { - lkd = m_date_gen_parser.get_last_kday_type(from, to, a_ios, *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - kday_before_type& fkb) const - { - fkb = m_date_gen_parser.get_kday_before_type(from, to, a_ios, *this); - return from; - } - InItrT get(InItrT& from, - InItrT& to, - std::ios_base& a_ios, - kday_after_type& fka) const - { - fka = m_date_gen_parser.get_kday_after_type(from, to, a_ios, *this); - return from; - } - - protected: - string_type m_format; - string_type m_month_format; - string_type m_weekday_format; - string_type m_year_format; - format_date_parser_type m_parser; - date_gen_parser_type m_date_gen_parser; - period_parser_type m_period_parser; - special_values_parser_type m_sv_parser; - private: - }; - - - template - std::locale::id date_input_facet::id; - - template - const typename date_input_facet::char_type - date_input_facet::long_weekday_format[3] = {'%','A'}; - - template - const typename date_input_facet::char_type - date_input_facet::short_weekday_format[3] = {'%','a'}; - - template - const typename date_input_facet::char_type - date_input_facet::long_month_format[3] = {'%','B'}; - - template - const typename date_input_facet::char_type - date_input_facet::short_month_format[3] = {'%','b'}; - - template - const typename date_input_facet::char_type - date_input_facet::four_digit_year_format[3] = {'%','Y'}; - - template - const typename date_input_facet::char_type - date_input_facet::two_digit_year_format[3] = {'%','y'}; - - template - const typename date_input_facet::char_type - date_input_facet::default_period_separator[4] = { ' ', '/', ' '}; - - template - const typename date_input_facet::char_type - date_input_facet::standard_format_specifier[3] = - {'%', 'x' }; - - template - const typename date_input_facet::char_type - date_input_facet::iso_format_specifier[7] = - {'%', 'Y', '%', 'm', '%', 'd' }; - - template - const typename date_input_facet::char_type - date_input_facet::iso_format_extended_specifier[9] = - {'%', 'Y', '-', '%', 'm', '-', '%', 'd' }; - - template - const typename date_input_facet::char_type - date_input_facet::default_date_format[9] = - {'%','Y','-','%','b','-','%','d'}; - -} } // namespaces - -#endif diff --git a/boost/date_time/date_format_simple.hpp b/boost/date_time/date_format_simple.hpp deleted file mode 100644 index 4529903..0000000 --- a/boost/date_time/date_format_simple.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef DATE_TIME_SIMPLE_FORMAT_HPP___ -#define DATE_TIME_SIMPLE_FORMAT_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/parse_format_base.hpp" - -namespace boost { -namespace date_time { - -//! Class to provide simple basic formatting rules -template -class simple_format { -public: - - //! String used printed is date is invalid - static const charT* not_a_date() - { - return "not-a-date-time"; - } - //! String used to for positive infinity value - static const charT* pos_infinity() - { - return "+infinity"; - } - //! String used to for positive infinity value - static const charT* neg_infinity() - { - return "-infinity"; - } - //! Describe month format - static month_format_spec month_format() - { - return month_as_short_string; - } - static ymd_order_spec date_order() - { - return ymd_order_iso; //YYYY-MM-DD - } - //! This format uses '-' to separate date elements - static bool has_date_sep_chars() - { - return true; - } - //! Char to sep? - static charT year_sep_char() - { - return '-'; - } - //! char between year-month - static charT month_sep_char() - { - return '-'; - } - //! Char to separate month-day - static charT day_sep_char() - { - return '-'; - } - //! char between date-hours - static charT hour_sep_char() - { - return ' '; - } - //! char between hour and minute - static charT minute_sep_char() - { - return ':'; - } - //! char for second - static charT second_sep_char() - { - return ':'; - } - -}; - -#ifndef BOOST_NO_STD_WSTRING - -//! Specialization of formmating rules for wchar_t -template<> -class simple_format { -public: - - //! String used printed is date is invalid - static const wchar_t* not_a_date() - { - return L"not-a-date-time"; - } - //! String used to for positive infinity value - static const wchar_t* pos_infinity() - { - return L"+infinity"; - } - //! String used to for positive infinity value - static const wchar_t* neg_infinity() - { - return L"-infinity"; - } - //! Describe month format - static month_format_spec month_format() - { - return month_as_short_string; - } - static ymd_order_spec date_order() - { - return ymd_order_iso; //YYYY-MM-DD - } - //! This format uses '-' to separate date elements - static bool has_date_sep_chars() - { - return true; - } - //! Char to sep? - static wchar_t year_sep_char() - { - return '-'; - } - //! char between year-month - static wchar_t month_sep_char() - { - return '-'; - } - //! Char to separate month-day - static wchar_t day_sep_char() - { - return '-'; - } - //! char between date-hours - static wchar_t hour_sep_char() - { - return ' '; - } - //! char between hour and minute - static wchar_t minute_sep_char() - { - return ':'; - } - //! char for second - static wchar_t second_sep_char() - { - return ':'; - } - -}; - -#endif // BOOST_NO_STD_WSTRING -} } //namespace date_time - - - - -#endif diff --git a/boost/date_time/date_formatting.hpp b/boost/date_time/date_formatting.hpp deleted file mode 100644 index c1b69a8..0000000 --- a/boost/date_time/date_formatting.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef DATE_TIME_DATE_FORMATTING_HPP___ -#define DATE_TIME_DATE_FORMATTING_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/iso_format.hpp" -#include "boost/date_time/compiler_config.hpp" -#include -#include -#include -#include - -/* NOTE: "formatter" code for older compilers, ones that define - * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in - * date_formatting_limited.hpp - */ - -namespace boost { -namespace date_time { - - //! Formats a month as as string into an ostream - template - class month_formatter - { - typedef std::basic_ostream ostream_type; - public: - //! Formats a month as as string into an ostream - /*! This function demands that month_type provide - * functions for converting to short and long strings - * if that capability is used. - */ - static ostream_type& format_month(const month_type& month, - ostream_type &os) - { - switch (format_type::month_format()) - { - case month_as_short_string: - { - os << month.as_short_string(); - break; - } - case month_as_long_string: - { - os << month.as_long_string(); - break; - } - case month_as_integer: - { - boost::io::basic_ios_fill_saver ifs(os); - os << std::setw(2) << std::setfill(os.widen('0')) << month.as_number(); - break; - } - default: - break; - - } - return os; - } // format_month - }; - - - //! Convert ymd to a standard string formatting policies - template - class ymd_formatter - { - public: - //! Convert ymd to a standard string formatting policies - /*! This is standard code for handling date formatting with - * year-month-day based date information. This function - * uses the format_type to control whether the string will - * contain separator characters, and if so what the character - * will be. In addtion, it can format the month as either - * an integer or a string as controled by the formatting - * policy - */ - static std::basic_string ymd_to_string(ymd_type ymd) - { - typedef typename ymd_type::month_type month_type; - std::basic_ostringstream ss; - - // Temporarily switch to classic locale to prevent possible formatting - // of year with comma or other character (for example 2,008). - ss.imbue(std::locale::classic()); - ss << ymd.year; - ss.imbue(std::locale()); - - if (format_type::has_date_sep_chars()) { - ss << format_type::month_sep_char(); - } - //this name is a bit ugly, oh well.... - month_formatter::format_month(ymd.month, ss); - if (format_type::has_date_sep_chars()) { - ss << format_type::day_sep_char(); - } - ss << std::setw(2) << std::setfill(ss.widen('0')) - << ymd.day; - return ss.str(); - } - }; - - - //! Convert a date to string using format policies - template - class date_formatter - { - public: - typedef std::basic_string string_type; - //! Convert to a date to standard string using format policies - static string_type date_to_string(date_type d) - { - typedef typename date_type::ymd_type ymd_type; - if (d.is_not_a_date()) { - return string_type(format_type::not_a_date()); - } - if (d.is_neg_infinity()) { - return string_type(format_type::neg_infinity()); - } - if (d.is_pos_infinity()) { - return string_type(format_type::pos_infinity()); - } - ymd_type ymd = d.year_month_day(); - return ymd_formatter::ymd_to_string(ymd); - } - }; - - -} } //namespace date_time - - -#endif - diff --git a/boost/date_time/date_formatting_limited.hpp b/boost/date_time/date_formatting_limited.hpp deleted file mode 100644 index 7c5c173..0000000 --- a/boost/date_time/date_formatting_limited.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ -#define DATE_TIME_DATE_FORMATTING_LIMITED_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/iso_format.hpp" -#include "boost/date_time/compiler_config.hpp" -#include -#include -#include - - -namespace boost { -namespace date_time { - - //! Formats a month as as string into an ostream - template - class month_formatter - { - public: - //! Formats a month as as string into an ostream - /*! This function demands that month_type provide - * functions for converting to short and long strings - * if that capability is used. - */ - static std::ostream& format_month(const month_type& month, - std::ostream& os) - { - switch (format_type::month_format()) - { - case month_as_short_string: - { - os << month.as_short_string(); - break; - } - case month_as_long_string: - { - os << month.as_long_string(); - break; - } - case month_as_integer: - { - os << std::setw(2) << std::setfill('0') << month.as_number(); - break; - } - - } - return os; - } // format_month - }; - - - //! Convert ymd to a standard string formatting policies - template - class ymd_formatter - { - public: - //! Convert ymd to a standard string formatting policies - /*! This is standard code for handling date formatting with - * year-month-day based date information. This function - * uses the format_type to control whether the string will - * contain separator characters, and if so what the character - * will be. In addtion, it can format the month as either - * an integer or a string as controled by the formatting - * policy - */ - static std::string ymd_to_string(ymd_type ymd) - { - typedef typename ymd_type::month_type month_type; - std::ostringstream ss; - ss << ymd.year; - if (format_type::has_date_sep_chars()) { - ss << format_type::month_sep_char(); - } - //this name is a bit ugly, oh well.... - month_formatter::format_month(ymd.month, ss); - if (format_type::has_date_sep_chars()) { - ss << format_type::day_sep_char(); - } - ss << std::setw(2) << std::setfill('0') - << ymd.day; - return ss.str(); - } - }; - - - //! Convert a date to string using format policies - template - class date_formatter - { - public: - //! Convert to a date to standard string using format policies - static std::string date_to_string(date_type d) - { - typedef typename date_type::ymd_type ymd_type; - if (d.is_not_a_date()) { - return format_type::not_a_date(); - } - if (d.is_neg_infinity()) { - return format_type::neg_infinity(); - } - if (d.is_pos_infinity()) { - return format_type::pos_infinity(); - } - ymd_type ymd = d.year_month_day(); - return ymd_formatter::ymd_to_string(ymd); - } - }; - - -} } //namespace date_time - - -#endif - diff --git a/boost/date_time/date_formatting_locales.hpp b/boost/date_time/date_formatting_locales.hpp deleted file mode 100644 index a1daad3..0000000 --- a/boost/date_time/date_formatting_locales.hpp +++ /dev/null @@ -1,234 +0,0 @@ -#ifndef DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ -#define DATE_TIME_DATE_FORMATTING_LOCALES_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - - -#include "boost/date_time/locale_config.hpp" // set BOOST_DATE_TIME_NO_LOCALE - -#ifndef BOOST_DATE_TIME_NO_LOCALE - -#include "boost/date_time/iso_format.hpp" -#include "boost/date_time/date_names_put.hpp" -#include "boost/date_time/parse_format_base.hpp" -#include -//#include -#include -#include - - -namespace boost { -namespace date_time { - - //! Formats a month as as string into an ostream - template - class ostream_month_formatter - { - public: - typedef typename facet_type::month_type month_type; - typedef std::basic_ostream ostream_type; - - //! Formats a month as as string into an output iterator - static void format_month(const month_type& month, - ostream_type& os, - const facet_type& f) - { - - switch (f.month_format()) - { - case month_as_short_string: - { - std::ostreambuf_iterator oitr(os); - f.put_month_short(oitr, month.as_enum()); - break; - } - case month_as_long_string: - { - std::ostreambuf_iterator oitr(os); - f.put_month_long(oitr, month.as_enum()); - break; - } - case month_as_integer: - { - boost::io::basic_ios_fill_saver ifs(os); - os << std::setw(2) << std::setfill(os.widen('0')) << month.as_number(); - break; - } - - } - } // format_month - - }; - - - //! Formats a weekday - template - class ostream_weekday_formatter - { - public: - typedef typename facet_type::month_type month_type; - typedef std::basic_ostream ostream_type; - - //! Formats a month as as string into an output iterator - static void format_weekday(const weekday_type& wd, - ostream_type& os, - const facet_type& f, - bool as_long_string) - { - - std::ostreambuf_iterator oitr(os); - if (as_long_string) { - f.put_weekday_long(oitr, wd.as_enum()); - } - else { - f.put_weekday_short(oitr, wd.as_enum()); - } - - } // format_weekday - - }; - - - //! Convert ymd to a standard string formatting policies - template - class ostream_ymd_formatter - { - public: - typedef typename ymd_type::month_type month_type; - typedef ostream_month_formatter month_formatter_type; - typedef std::basic_ostream ostream_type; - typedef std::basic_string foo_type; - - //! Convert ymd to a standard string formatting policies - /*! This is standard code for handling date formatting with - * year-month-day based date information. This function - * uses the format_type to control whether the string will - * contain separator characters, and if so what the character - * will be. In addtion, it can format the month as either - * an integer or a string as controled by the formatting - * policy - */ - // static string_type ymd_to_string(ymd_type ymd) -// { -// std::ostringstream ss; -// facet_type dnp; -// ymd_put(ymd, ss, dnp); -// return ss.str(); -// } - - - // Put ymd to ostream -- part of ostream refactor - static void ymd_put(ymd_type ymd, - ostream_type& os, - const facet_type& f) - { - boost::io::basic_ios_fill_saver ifs(os); - std::ostreambuf_iterator oitr(os); - switch (f.date_order()) { - case ymd_order_iso: { - os << ymd.year; - if (f.has_date_sep_chars()) { - f.month_sep_char(oitr); - } - month_formatter_type::format_month(ymd.month, os, f); - if (f.has_date_sep_chars()) { - f.day_sep_char(oitr); - } - os << std::setw(2) << std::setfill(os.widen('0')) - << ymd.day; - break; - } - case ymd_order_us: { - month_formatter_type::format_month(ymd.month, os, f); - if (f.has_date_sep_chars()) { - f.day_sep_char(oitr); - } - os << std::setw(2) << std::setfill(os.widen('0')) - << ymd.day; - if (f.has_date_sep_chars()) { - f.month_sep_char(oitr); - } - os << ymd.year; - break; - } - case ymd_order_dmy: { - os << std::setw(2) << std::setfill(os.widen('0')) - << ymd.day; - if (f.has_date_sep_chars()) { - f.day_sep_char(oitr); - } - month_formatter_type::format_month(ymd.month, os, f); - if (f.has_date_sep_chars()) { - f.month_sep_char(oitr); - } - os << ymd.year; - break; - } - } - } - }; - - - //! Convert a date to string using format policies - template - class ostream_date_formatter - { - public: - typedef std::basic_ostream ostream_type; - typedef typename date_type::ymd_type ymd_type; - - //! Put date into an ostream - static void date_put(const date_type& d, - ostream_type& os, - const facet_type& f) - { - special_values sv = d.as_special(); - if (sv == not_special) { - ymd_type ymd = d.year_month_day(); - ostream_ymd_formatter::ymd_put(ymd, os, f); - } - else { // output a special value - std::ostreambuf_iterator coi(os); - f.put_special_value(coi, sv); - } - } - - - //! Put date into an ostream - static void date_put(const date_type& d, - ostream_type& os) - { - //retrieve the local from the ostream - std::locale locale = os.getloc(); - if (std::has_facet(locale)) { - const facet_type& f = std::use_facet(locale); - date_put(d, os, f); - } - else { - //default to something sensible if no facet installed - facet_type default_facet; - date_put(d, os, default_facet); - } - } // date_to_ostream - }; //class date_formatter - - -} } //namespace date_time - -#endif - -#endif - diff --git a/boost/date_time/date_generator_formatter.hpp b/boost/date_time/date_generator_formatter.hpp deleted file mode 100644 index 42c396b..0000000 --- a/boost/date_time/date_generator_formatter.hpp +++ /dev/null @@ -1,265 +0,0 @@ -#ifndef _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ -#define _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ - -/* Copyright (c) 2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include "boost/date_time/date_generators.hpp" - -namespace boost { -namespace date_time { - - //! Formats date_generators for output - /*! Formatting of date_generators follows specific orders for the - * various types of date_generators. - * - partial_date => "dd Month" - * - nth_day_of_the_week_in_month => "nth weekday of month" - * - first_day_of_the_week_in_month => "first weekday of month" - * - last_day_of_the_week_in_month => "last weekday of month" - * - first_day_of_the_week_after => "weekday after" - * - first_day_of_the_week_before => "weekday before" - * While the order of the elements in these phrases cannot be changed, - * the elements themselves can be. Weekday and Month get their formats - * and names from the date_facet. The remaining elements are stored in - * the date_generator_formatter and can be customized upon construction - * or via a member function. The default elements are those shown in the - * examples above. - */ - template > > - class date_generator_formatter { - public: - typedef partial_date partial_date_type; - typedef nth_kday_of_month nth_kday_type; - typedef first_kday_of_month first_kday_type; - typedef last_kday_of_month last_kday_type; - typedef first_kday_after kday_after_type; - typedef first_kday_before kday_before_type; - - typedef CharT char_type; - typedef std::basic_string string_type; - typedef std::vector collection_type; - static const char_type first_string[6]; - static const char_type second_string[7]; - static const char_type third_string[6]; - static const char_type fourth_string[7]; - static const char_type fifth_string[6]; - static const char_type last_string[5]; - static const char_type before_string[8]; - static const char_type after_string[6]; - static const char_type of_string[3]; - - enum phrase_elements {first=0, second, third, fourth, fifth, last, - before, after, of, number_of_phrase_elements}; - - //! Default format elements used - date_generator_formatter() - { - phrase_strings.reserve(number_of_phrase_elements); - phrase_strings.push_back(string_type(first_string)); - phrase_strings.push_back(string_type(second_string)); - phrase_strings.push_back(string_type(third_string)); - phrase_strings.push_back(string_type(fourth_string)); - phrase_strings.push_back(string_type(fifth_string)); - phrase_strings.push_back(string_type(last_string)); - phrase_strings.push_back(string_type(before_string)); - phrase_strings.push_back(string_type(after_string)); - phrase_strings.push_back(string_type(of_string)); - } - - //! Constructor that allows for a custom set of phrase elements - date_generator_formatter(const string_type& first_str, - const string_type& second_str, - const string_type& third_str, - const string_type& fourth_str, - const string_type& fifth_str, - const string_type& last_str, - const string_type& before_str, - const string_type& after_str, - const string_type& of_str) - { - phrase_strings.reserve(number_of_phrase_elements); - phrase_strings.push_back(first_str); - phrase_strings.push_back(second_str); - phrase_strings.push_back(third_str); - phrase_strings.push_back(fourth_str); - phrase_strings.push_back(fifth_str); - phrase_strings.push_back(last_str); - phrase_strings.push_back(before_str); - phrase_strings.push_back(after_str); - phrase_strings.push_back(of_str); - } - - //! Replace the set of phrase elements with those contained in new_strings - /*! The order of the strings in the given collection is important. - * They must follow: - * - first, second, third, fourth, fifth, last, before, after, of. - * - * It is not necessary to send in a complete set if only a few - * elements are to be replaced as long as the correct beg_pos is used. - * - * Ex: To keep the default first through fifth elements, but replace - * the rest with a collection of: - * - "final", "prior", "following", "in". - * The beg_pos of date_generator_formatter::last would be used. - */ - void elements(const collection_type& new_strings, - phrase_elements beg_pos=first) - { - if(beg_pos < number_of_phrase_elements) { - typename collection_type::iterator itr = phrase_strings.begin(); - itr += beg_pos; - std::copy(new_strings.begin(), new_strings.end(), - itr); - //phrase_strings.begin()); - } - } - - //!Put a partial_date => "dd Month" - template - OutItrT put_partial_date(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const partial_date_type& pd, - const facet_type& facet) const - { - facet.put(next, a_ios, a_fill, pd.day()); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, pd.month()); - return next; - } - - //! Put an nth_day_of_the_week_in_month => "nth weekday of month" - template - OutItrT put_nth_kday(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const nth_kday_type& nkd, - const facet_type& facet) const - { - put_string(next, phrase_strings[nkd.nth_week() -1]); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, nkd.day_of_week()); - next = a_fill; //TODO change this ??? - put_string(next, string_type(of_string)); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, nkd.month()); - return next; - } - - //! Put a first_day_of_the_week_in_month => "first weekday of month" - template - OutItrT put_first_kday(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const first_kday_type& fkd, - const facet_type& facet) const - { - put_string(next, phrase_strings[first]); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, fkd.day_of_week()); - next = a_fill; //TODO change this ??? - put_string(next, string_type(of_string)); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, fkd.month()); - return next; - } - - //! Put a last_day_of_the_week_in_month => "last weekday of month" - template - OutItrT put_last_kday(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const last_kday_type& lkd, - const facet_type& facet) const - { - put_string(next, phrase_strings[last]); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, lkd.day_of_week()); - next = a_fill; //TODO change this ??? - put_string(next, string_type(of_string)); - next = a_fill; //TODO change this ??? - facet.put(next, a_ios, a_fill, lkd.month()); - return next; - } - - //! Put a first_day_of_the_week_before => "weekday before" - template - OutItrT put_kday_before(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const kday_before_type& fkb, - const facet_type& facet) const - { - facet.put(next, a_ios, a_fill, fkb.day_of_week()); - next = a_fill; //TODO change this ??? - put_string(next, phrase_strings[before]); - return next; - } - - //! Put a first_day_of_the_week_after => "weekday after" - template - OutItrT put_kday_after(OutItrT next, std::ios_base& a_ios, - CharT a_fill, const kday_after_type& fka, - const facet_type& facet) const - { - facet.put(next, a_ios, a_fill, fka.day_of_week()); - next = a_fill; //TODO change this ??? - put_string(next, phrase_strings[after]); - return next; - } - - - private: - collection_type phrase_strings; - - //! helper function to put the various member string into stream - OutItrT put_string(OutItrT next, const string_type& str) const - { - typename string_type::const_iterator itr = str.begin(); - while(itr != str.end()) { - *next = *itr; - ++itr; - ++next; - } - return next; - } - }; - - template - const typename date_generator_formatter::char_type - date_generator_formatter::first_string[6] = - {'f','i','r','s','t'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::second_string[7] = - {'s','e','c','o','n','d'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::third_string[6] = - {'t','h','i','r','d'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::fourth_string[7] = - {'f','o','u','r','t','h'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::fifth_string[6] = - {'f','i','f','t','h'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::last_string[5] = - {'l','a','s','t'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::before_string[8] = - {'b','e','f','o','r','e'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::after_string[6] = - {'a','f','t','e','r'}; - template - const typename date_generator_formatter::char_type - date_generator_formatter::of_string[3] = - {'o','f'}; -} } // namespaces - -#endif // _DATE_TIME_DATE_GENERATOR_FORMATTER__HPP___ diff --git a/boost/date_time/date_generator_parser.hpp b/boost/date_time/date_generator_parser.hpp deleted file mode 100644 index f4d7b27..0000000 --- a/boost/date_time/date_generator_parser.hpp +++ /dev/null @@ -1,330 +0,0 @@ - -#ifndef DATE_TIME_DATE_GENERATOR_PARSER_HPP__ -#define DATE_TIME_DATE_GENERATOR_PARSER_HPP__ - -/* Copyright (c) 2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include // istreambuf_iterator -#include -#include -#include -#include -#include - -namespace boost { namespace date_time { - - //! Class for date_generator parsing - /*! The elements of a date_generator "phrase" are parsed from the input stream in a - * particular order. All elements are required and the order in which they appear - * cannot change, however, the elements themselves can be changed. The default - * elements and their order are as follows: - * - * - partial_date => "dd Month" - * - nth_day_of_the_week_in_month => "nth weekday of month" - * - first_day_of_the_week_in_month => "first weekday of month" - * - last_day_of_the_week_in_month => "last weekday of month" - * - first_day_of_the_week_after => "weekday after" - * - first_day_of_the_week_before => "weekday before" - * - * Weekday and Month names and formats are handled via the date_input_facet. - * - */ - template - class date_generator_parser - { - public: - typedef std::basic_string string_type; - typedef std::istreambuf_iterator stream_itr_type; - - typedef typename date_type::month_type month_type; - typedef typename date_type::day_of_week_type day_of_week_type; - typedef typename date_type::day_type day_type; - - typedef string_parse_tree parse_tree_type; - typedef typename parse_tree_type::parse_match_result_type match_results; - typedef std::vector > collection_type; - - typedef partial_date partial_date_type; - typedef nth_kday_of_month nth_kday_type; - typedef first_kday_of_month first_kday_type; - typedef last_kday_of_month last_kday_type; - typedef first_kday_after kday_after_type; - typedef first_kday_before kday_before_type; - - typedef charT char_type; - static const char_type first_string[6]; - static const char_type second_string[7]; - static const char_type third_string[6]; - static const char_type fourth_string[7]; - static const char_type fifth_string[6]; - static const char_type last_string[5]; - static const char_type before_string[8]; - static const char_type after_string[6]; - static const char_type of_string[3]; - - enum phrase_elements {first=0, second, third, fourth, fifth, last, - before, after, of, number_of_phrase_elements}; - - //! Creates a date_generator_parser with the default set of "element_strings" - date_generator_parser() - { - element_strings(string_type(first_string), - string_type(second_string), - string_type(third_string), - string_type(fourth_string), - string_type(fifth_string), - string_type(last_string), - string_type(before_string), - string_type(after_string), - string_type(of_string)); - } - - //! Creates a date_generator_parser using a user defined set of element strings - date_generator_parser(const string_type& first_str, - const string_type& second_str, - const string_type& third_str, - const string_type& fourth_str, - const string_type& fifth_str, - const string_type& last_str, - const string_type& before_str, - const string_type& after_str, - const string_type& of_str) - { - element_strings(first_str, second_str, third_str, fourth_str, fifth_str, - last_str, before_str, after_str, of_str); - } - - //! Replace strings that determine nth week for generator - void element_strings(const string_type& first_str, - const string_type& second_str, - const string_type& third_str, - const string_type& fourth_str, - const string_type& fifth_str, - const string_type& last_str, - const string_type& before_str, - const string_type& after_str, - const string_type& of_str) - { - collection_type phrases; - phrases.push_back(first_str); - phrases.push_back(second_str); - phrases.push_back(third_str); - phrases.push_back(fourth_str); - phrases.push_back(fifth_str); - phrases.push_back(last_str); - phrases.push_back(before_str); - phrases.push_back(after_str); - phrases.push_back(of_str); - m_element_strings = parse_tree_type(phrases, this->first); // enum first - } - - void element_strings(const collection_type& col) - { - m_element_strings = parse_tree_type(col, this->first); // enum first - } - - //! returns partial_date parsed from stream - template - partial_date_type - get_partial_date_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - day_type d(1); - month_type m(1); - facet.get(sitr, stream_end, a_ios, d); - facet.get(sitr, stream_end, a_ios, m); - - return partial_date_type(d,m); - } - - //! returns nth_kday_of_week parsed from stream - template - nth_kday_type - get_nth_kday_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - typename nth_kday_type::week_num wn; - day_of_week_type wd(0); // no default constructor - month_type m(1); // no default constructor - - match_results mr = m_element_strings.match(sitr, stream_end); - switch(mr.current_match) { - case first : { wn = nth_kday_type::first; break; } - case second : { wn = nth_kday_type::second; break; } - case third : { wn = nth_kday_type::third; break; } - case fourth : { wn = nth_kday_type::fourth; break; } - case fifth : { wn = nth_kday_type::fifth; break; } - default: - { - boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); - BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(wn = nth_kday_type::first); - } - } // week num - facet.get(sitr, stream_end, a_ios, wd); // day_of_week - extract_element(sitr, stream_end, of); // "of" element - facet.get(sitr, stream_end, a_ios, m); // month - - return nth_kday_type(wn, wd, m); - } - - //! returns first_kday_of_week parsed from stream - template - first_kday_type - get_first_kday_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - day_of_week_type wd(0); // no default constructor - month_type m(1); // no default constructor - - extract_element(sitr, stream_end, first); // "first" element - facet.get(sitr, stream_end, a_ios, wd); // day_of_week - extract_element(sitr, stream_end, of); // "of" element - facet.get(sitr, stream_end, a_ios, m); // month - - - return first_kday_type(wd, m); - } - - //! returns last_kday_of_week parsed from stream - template - last_kday_type - get_last_kday_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - day_of_week_type wd(0); // no default constructor - month_type m(1); // no default constructor - - extract_element(sitr, stream_end, last); // "last" element - facet.get(sitr, stream_end, a_ios, wd); // day_of_week - extract_element(sitr, stream_end, of); // "of" element - facet.get(sitr, stream_end, a_ios, m); // month - - - return last_kday_type(wd, m); - } - - //! returns first_kday_of_week parsed from stream - template - kday_before_type - get_kday_before_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - day_of_week_type wd(0); // no default constructor - - facet.get(sitr, stream_end, a_ios, wd); // day_of_week - extract_element(sitr, stream_end, before);// "before" element - - return kday_before_type(wd); - } - - //! returns first_kday_of_week parsed from stream - template - kday_after_type - get_kday_after_type(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - day_of_week_type wd(0); // no default constructor - - facet.get(sitr, stream_end, a_ios, wd); // day_of_week - extract_element(sitr, stream_end, after); // "after" element - - return kday_after_type(wd); - } - - private: - parse_tree_type m_element_strings; - - //! Extracts phrase element from input. Throws ios_base::failure on error. - void extract_element(stream_itr_type& sitr, - stream_itr_type& stream_end, - typename date_generator_parser::phrase_elements ele) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - match_results mr = m_element_strings.match(sitr, stream_end); - if(mr.current_match != ele) { - boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + mr.cache + "'")); - } - } - - }; - - template - const typename date_generator_parser::char_type - date_generator_parser::first_string[6] = - {'f','i','r','s','t'}; - template - const typename date_generator_parser::char_type - date_generator_parser::second_string[7] = - {'s','e','c','o','n','d'}; - template - const typename date_generator_parser::char_type - date_generator_parser::third_string[6] = - {'t','h','i','r','d'}; - template - const typename date_generator_parser::char_type - date_generator_parser::fourth_string[7] = - {'f','o','u','r','t','h'}; - template - const typename date_generator_parser::char_type - date_generator_parser::fifth_string[6] = - {'f','i','f','t','h'}; - template - const typename date_generator_parser::char_type - date_generator_parser::last_string[5] = - {'l','a','s','t'}; - template - const typename date_generator_parser::char_type - date_generator_parser::before_string[8] = - {'b','e','f','o','r','e'}; - template - const typename date_generator_parser::char_type - date_generator_parser::after_string[6] = - {'a','f','t','e','r'}; - template - const typename date_generator_parser::char_type - date_generator_parser::of_string[3] = - {'o','f'}; - -} } //namespace - -#endif // DATE_TIME_DATE_GENERATOR_PARSER_HPP__ - diff --git a/boost/date_time/date_names_put.hpp b/boost/date_time/date_names_put.hpp deleted file mode 100644 index 20da2d2..0000000 --- a/boost/date_time/date_names_put.hpp +++ /dev/null @@ -1,321 +0,0 @@ -#ifndef DATE_TIME_DATE_NAMES_PUT_HPP___ -#define DATE_TIME_DATE_NAMES_PUT_HPP___ - -/* Copyright (c) 2002-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - - -#include // set BOOST_DATE_TIME_NO_LOCALE - -#ifndef BOOST_DATE_TIME_NO_LOCALE - -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace date_time { - - //! Output facet base class for gregorian dates. - /*! This class is a base class for date facets used to localize the - * names of months and the names of days in the week. - * - * Requirements of Config - * - define an enumeration month_enum that enumerates the months. - * The enumeration should be '1' based eg: Jan==1 - * - define as_short_string and as_long_string - * - * (see langer & kreft p334). - * - */ - template > - class BOOST_SYMBOL_VISIBLE date_names_put : public std::locale::facet - { - public: - date_names_put() {} - typedef OutputIterator iter_type; - typedef typename Config::month_type month_type; - typedef typename Config::month_enum month_enum; - typedef typename Config::weekday_enum weekday_enum; - typedef typename Config::special_value_enum special_value_enum; - //typedef typename Config::format_type format_type; - typedef std::basic_string string_type; - typedef charT char_type; - static const char_type default_special_value_names[3][17]; - static const char_type separator[2]; - - static std::locale::id id; - -#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) - std::locale::id& __get_id (void) const { return id; } -#endif - - void put_special_value(iter_type& oitr, special_value_enum sv) const - { - do_put_special_value(oitr, sv); - } - void put_month_short(iter_type& oitr, month_enum moy) const - { - do_put_month_short(oitr, moy); - } - void put_month_long(iter_type& oitr, month_enum moy) const - { - do_put_month_long(oitr, moy); - } - void put_weekday_short(iter_type& oitr, weekday_enum wd) const - { - do_put_weekday_short(oitr, wd); - } - void put_weekday_long(iter_type& oitr, weekday_enum wd) const - { - do_put_weekday_long(oitr, wd); - } - bool has_date_sep_chars() const - { - return do_has_date_sep_chars(); - } - void year_sep_char(iter_type& oitr) const - { - do_year_sep_char(oitr); - } - //! char between year-month - void month_sep_char(iter_type& oitr) const - { - do_month_sep_char(oitr); - } - //! Char to separate month-day - void day_sep_char(iter_type& oitr) const - { - do_day_sep_char(oitr); - } - //! Determines the order to put the date elements - ymd_order_spec date_order() const - { - return do_date_order(); - } - //! Determines if month is displayed as integer, short or long string - month_format_spec month_format() const - { - return do_month_format(); - } - - protected: - //! Default facet implementation uses month_type defaults - virtual void do_put_month_short(iter_type& oitr, month_enum moy) const - { - month_type gm(moy); - charT c = '\0'; - put_string(oitr, gm.as_short_string(c)); - } - //! Default facet implementation uses month_type defaults - virtual void do_put_month_long(iter_type& oitr, - month_enum moy) const - { - month_type gm(moy); - charT c = '\0'; - put_string(oitr, gm.as_long_string(c)); - } - //! Default facet implementation for special value types - virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const - { - if(sv <= 2) { // only output not_a_date_time, neg_infin, or pos_infin - string_type s(default_special_value_names[sv]); - put_string(oitr, s); - } - } - virtual void do_put_weekday_short(iter_type&, weekday_enum) const - { - } - virtual void do_put_weekday_long(iter_type&, weekday_enum) const - { - } - virtual bool do_has_date_sep_chars() const - { - return true; - } - virtual void do_year_sep_char(iter_type& oitr) const - { - string_type s(separator); - put_string(oitr, s); - } - //! char between year-month - virtual void do_month_sep_char(iter_type& oitr) const - { - string_type s(separator); - put_string(oitr, s); - } - //! Char to separate month-day - virtual void do_day_sep_char(iter_type& oitr) const - { - string_type s(separator); //put in '-' - put_string(oitr, s); - } - //! Default for date order - virtual ymd_order_spec do_date_order() const - { - return ymd_order_iso; - } - //! Default month format - virtual month_format_spec do_month_format() const - { - return month_as_short_string; - } - void put_string(iter_type& oi, const charT* const s) const - { - string_type s1(boost::lexical_cast(s)); - typename string_type::iterator si,end; - for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { - *oi = *si; - } - } - void put_string(iter_type& oi, const string_type& s1) const - { - typename string_type::const_iterator si,end; - for (si=s1.begin(), end=s1.end(); si!=end; si++, oi++) { - *oi = *si; - } - } - }; - - template - const typename date_names_put::char_type - date_names_put::default_special_value_names[3][17] = { - {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, - {'-','i','n','f','i','n','i','t','y'}, - {'+','i','n','f','i','n','i','t','y'} }; - - template - const typename date_names_put::char_type - date_names_put::separator[2] = - {'-', '\0'} ; - - - //! Generate storage location for a std::locale::id - template - std::locale::id date_names_put::id; - - //! A date name output facet that takes an array of char* to define strings - template > - class BOOST_SYMBOL_VISIBLE all_date_names_put : public date_names_put - { - public: - all_date_names_put(const charT* const month_short_names[], - const charT* const month_long_names[], - const charT* const special_value_names[], - const charT* const weekday_short_names[], - const charT* const weekday_long_names[], - charT separator_char = '-', - ymd_order_spec order_spec = ymd_order_iso, - month_format_spec month_format = month_as_short_string) : - month_short_names_(month_short_names), - month_long_names_(month_long_names), - special_value_names_(special_value_names), - weekday_short_names_(weekday_short_names), - weekday_long_names_(weekday_long_names), - order_spec_(order_spec), - month_format_spec_(month_format) - { - separator_char_[0] = separator_char; - separator_char_[1] = '\0'; - - } - typedef OutputIterator iter_type; - typedef typename Config::month_enum month_enum; - typedef typename Config::weekday_enum weekday_enum; - typedef typename Config::special_value_enum special_value_enum; - - const charT* const* get_short_month_names() const - { - return month_short_names_; - } - const charT* const* get_long_month_names() const - { - return month_long_names_; - } - const charT* const* get_special_value_names() const - { - return special_value_names_; - } - const charT* const* get_short_weekday_names()const - { - return weekday_short_names_; - } - const charT* const* get_long_weekday_names()const - { - return weekday_long_names_; - } - - protected: - //! Generic facet that takes array of chars - virtual void do_put_month_short(iter_type& oitr, month_enum moy) const - { - this->put_string(oitr, month_short_names_[moy-1]); - } - //! Long month names - virtual void do_put_month_long(iter_type& oitr, month_enum moy) const - { - this->put_string(oitr, month_long_names_[moy-1]); - } - //! Special values names - virtual void do_put_special_value(iter_type& oitr, special_value_enum sv) const - { - this->put_string(oitr, special_value_names_[sv]); - } - virtual void do_put_weekday_short(iter_type& oitr, weekday_enum wd) const - { - this->put_string(oitr, weekday_short_names_[wd]); - } - virtual void do_put_weekday_long(iter_type& oitr, weekday_enum wd) const - { - this->put_string(oitr, weekday_long_names_[wd]); - } - //! char between year-month - virtual void do_month_sep_char(iter_type& oitr) const - { - this->put_string(oitr, separator_char_); - } - //! Char to separate month-day - virtual void do_day_sep_char(iter_type& oitr) const - { - this->put_string(oitr, separator_char_); - } - //! Set the date ordering - virtual ymd_order_spec do_date_order() const - { - return order_spec_; - } - //! Set the date ordering - virtual month_format_spec do_month_format() const - { - return month_format_spec_; - } - - private: - const charT* const* month_short_names_; - const charT* const* month_long_names_; - const charT* const* special_value_names_; - const charT* const* weekday_short_names_; - const charT* const* weekday_long_names_; - charT separator_char_[2]; - ymd_order_spec order_spec_; - month_format_spec month_format_spec_; - }; - -} } //namespace boost::date_time - -#endif //BOOST_NO_STD_LOCALE - -#endif diff --git a/boost/date_time/date_parsing.hpp b/boost/date_time/date_parsing.hpp deleted file mode 100644 index 34e39bd..0000000 --- a/boost/date_time/date_parsing.hpp +++ /dev/null @@ -1,342 +0,0 @@ -#ifndef _DATE_TIME_DATE_PARSING_HPP___ -#define _DATE_TIME_DATE_PARSING_HPP___ - -/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(BOOST_DATE_TIME_NO_LOCALE) -#include // ::tolower(int) -#else -#include // std::tolower(char, locale) -#endif - -namespace boost { -namespace date_time { - - //! A function to replace the std::transform( , , ,tolower) construct - /*! This function simply takes a string, and changes all the characters - * in that string to lowercase (according to the default system locale). - * In the event that a compiler does not support locales, the old - * C style tolower() is used. - */ - inline - std::string - convert_to_lower(std::string inp) - { -#if !defined(BOOST_DATE_TIME_NO_LOCALE) - const std::locale loc(std::locale::classic()); -#endif - std::string::size_type i = 0, n = inp.length(); - for (; i < n; ++i) { - inp[i] = -#if defined(BOOST_DATE_TIME_NO_LOCALE) - static_cast(std::tolower(inp[i])); -#else - // tolower and others were brought in to std for borland >= v564 - // in compiler_config.hpp - std::tolower(inp[i], loc); -#endif - } - return inp; - } - - //! Helper function for parse_date. - template - inline unsigned short - month_str_to_ushort(std::string const& s) { - if((s.at(0) >= '0') && (s.at(0) <= '9')) { - return boost::lexical_cast(s); - } - else { - std::string str = convert_to_lower(s); - //c++98 support -#if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) - static std::map month_map; - typedef std::map::value_type vtype; - if( month_map.empty() ) { - month_map.insert( vtype("jan", static_cast(1)) ); - month_map.insert( vtype("january", static_cast(1)) ); - month_map.insert( vtype("feb", static_cast(2)) ); - month_map.insert( vtype("february", static_cast(2)) ); - month_map.insert( vtype("mar", static_cast(3)) ); - month_map.insert( vtype("march", static_cast(3)) ); - month_map.insert( vtype("apr", static_cast(4)) ); - month_map.insert( vtype("april", static_cast(4)) ); - month_map.insert( vtype("may", static_cast(5)) ); - month_map.insert( vtype("jun", static_cast(6)) ); - month_map.insert( vtype("june", static_cast(6)) ); - month_map.insert( vtype("jul", static_cast(7)) ); - month_map.insert( vtype("july", static_cast(7)) ); - month_map.insert( vtype("aug", static_cast(8)) ); - month_map.insert( vtype("august", static_cast(8)) ); - month_map.insert( vtype("sep", static_cast(9)) ); - month_map.insert( vtype("september", static_cast(9)) ); - month_map.insert( vtype("oct", static_cast(10)) ); - month_map.insert( vtype("october", static_cast(10)) ); - month_map.insert( vtype("nov", static_cast(11)) ); - month_map.insert( vtype("november", static_cast(11)) ); - month_map.insert( vtype("dec", static_cast(12)) ); - month_map.insert( vtype("december", static_cast(12)) ); - } -#else //c+11 and beyond - static std::map month_map = - { { "jan", static_cast(1) }, { "january", static_cast(1) }, - { "feb", static_cast(2) }, { "february", static_cast(2) }, - { "mar", static_cast(3) }, { "march", static_cast(3) }, - { "apr", static_cast(4) }, { "april", static_cast(4) }, - { "may", static_cast(5) }, - { "jun", static_cast(6) }, { "june", static_cast(6) }, - { "jul", static_cast(7) }, { "july", static_cast(7) }, - { "aug", static_cast(8) }, { "august", static_cast(8) }, - { "sep", static_cast(9) }, { "september", static_cast(9) }, - { "oct", static_cast(10) }, { "october", static_cast(10)}, - { "nov", static_cast(11) }, { "november", static_cast(11)}, - { "dec", static_cast(12) }, { "december", static_cast(12)} - }; -#endif - std::map::const_iterator mitr = month_map.find( str ); - if ( mitr != month_map.end() ) { - return mitr->second; - } - } - return 13; // intentionally out of range - name not found - } - - - //! Generic function to parse a delimited date (eg: 2002-02-10) - /*! Accepted formats are: "2003-02-10" or " 2003-Feb-10" or - * "2003-Feburary-10" - * The order in which the Month, Day, & Year appear in the argument - * string can be accomodated by passing in the appropriate ymd_order_spec - */ - template - date_type - parse_date(const std::string& s, int order_spec = ymd_order_iso) { - std::string spec_str; - if(order_spec == ymd_order_iso) { - spec_str = "ymd"; - } - else if(order_spec == ymd_order_dmy) { - spec_str = "dmy"; - } - else { // (order_spec == ymd_order_us) - spec_str = "mdy"; - } - - typedef typename date_type::month_type month_type; - unsigned pos = 0; - unsigned short year(0), month(0), day(0); - typedef typename std::basic_string::traits_type traits_type; - typedef boost::char_separator char_separator_type; - typedef boost::tokenizer::const_iterator, - std::basic_string > tokenizer; - typedef boost::tokenizer::const_iterator, - std::basic_string >::iterator tokenizer_iterator; - // may need more delimiters, these work for the regression tests - const char sep_char[] = {',','-','.',' ','/','\0'}; - char_separator_type sep(sep_char); - tokenizer tok(s,sep); - for(tokenizer_iterator beg=tok.begin(); - beg!=tok.end() && pos < spec_str.size(); - ++beg, ++pos) { - switch(spec_str.at(pos)) { - case 'y': - { - year = boost::lexical_cast(*beg); - break; - } - case 'm': - { - month = month_str_to_ushort(*beg); - break; - } - case 'd': - { - day = boost::lexical_cast(*beg); - break; - } - default: break; - } //switch - } - return date_type(year, month, day); - } - - //! Generic function to parse undelimited date (eg: 20020201) - template - date_type - parse_undelimited_date(const std::string& s) { - int offsets[] = {4,2,2}; - int pos = 0; - //typename date_type::ymd_type ymd((year_type::min)(),1,1); - unsigned short y = 0, m = 0, d = 0; - - /* The two bool arguments state that parsing will not wrap - * (only the first 8 characters will be parsed) and partial - * strings will not be parsed. - * Ex: - * "2005121" will parse 2005 & 12, but not the "1" */ - boost::offset_separator osf(offsets, offsets+3, false, false); - - typedef typename boost::tokenizer::const_iterator, - std::basic_string > tokenizer_type; - tokenizer_type tok(s, osf); - for(typename tokenizer_type::iterator ti=tok.begin(); ti!=tok.end();++ti) { - unsigned short i = boost::lexical_cast(*ti); - switch(pos) { - case 0: y = i; break; - case 1: m = i; break; - case 2: d = i; break; - default: break; - } - pos++; - } - return date_type(y,m,d); - } - - //! Helper function for 'date gregorian::from_stream()' - /*! Creates a string from the iterators that reference the - * begining & end of a char[] or string. All elements are - * used in output string */ - template - inline - date_type - from_stream_type(iterator_type& beg, - iterator_type const& end, - char) - { - std::ostringstream ss; - while(beg != end) { - ss << *beg++; - } - return parse_date(ss.str()); - } - - //! Helper function for 'date gregorian::from_stream()' - /*! Returns the first string found in the stream referenced by the - * begining & end iterators */ - template - inline - date_type - from_stream_type(iterator_type& beg, - iterator_type const& /* end */, - std::string const&) - { - return parse_date(*beg); - } - - /* I believe the wchar stuff would be best elsewhere, perhaps in - * parse_date<>()? In the mean time this gets us started... */ - //! Helper function for 'date gregorian::from_stream()' - /*! Creates a string from the iterators that reference the - * begining & end of a wstring. All elements are - * used in output string */ - template - inline - date_type from_stream_type(iterator_type& beg, - iterator_type const& end, - wchar_t) - { - std::ostringstream ss; -#if !defined(BOOST_DATE_TIME_NO_LOCALE) - std::locale loc; - std::ctype const& fac = std::use_facet >(loc); - while(beg != end) { - ss << fac.narrow(*beg++, 'X'); // 'X' will cause exception to be thrown - } -#else - while(beg != end) { - char c = 'X'; // 'X' will cause exception to be thrown - const wchar_t wc = *beg++; - if (wc >= 0 && wc <= 127) - c = static_cast< char >(wc); - ss << c; - } -#endif - return parse_date(ss.str()); - } -#ifndef BOOST_NO_STD_WSTRING - //! Helper function for 'date gregorian::from_stream()' - /*! Creates a string from the first wstring found in the stream - * referenced by the begining & end iterators */ - template - inline - date_type - from_stream_type(iterator_type& beg, - iterator_type const& /* end */, - std::wstring const&) { - std::wstring ws = *beg; - std::ostringstream ss; - std::wstring::iterator wsb = ws.begin(), wse = ws.end(); -#if !defined(BOOST_DATE_TIME_NO_LOCALE) - std::locale loc; - std::ctype const& fac = std::use_facet >(loc); - while(wsb != wse) { - ss << fac.narrow(*wsb++, 'X'); // 'X' will cause exception to be thrown - } -#else - while(wsb != wse) { - char c = 'X'; // 'X' will cause exception to be thrown - const wchar_t wc = *wsb++; - if (wc >= 0 && wc <= 127) - c = static_cast< char >(wc); - ss << c; - } -#endif - return parse_date(ss.str()); - } -#endif // BOOST_NO_STD_WSTRING -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings -#else - //! function called by wrapper functions: date_period_from_(w)string() - template - period - from_simple_string_type(const std::basic_string& s){ - typedef typename std::basic_string::traits_type traits_type; - typedef typename boost::char_separator char_separator; - typedef typename boost::tokenizer::const_iterator, - std::basic_string > tokenizer; - const charT sep_list[4] = {'[','/',']','\0'}; - char_separator sep(sep_list); - tokenizer tokens(s, sep); - typename tokenizer::iterator tok_it = tokens.begin(); - std::basic_string date_string = *tok_it; - // get 2 string iterators and generate a date from them - typename std::basic_string::iterator date_string_start = date_string.begin(), - date_string_end = date_string.end(); - typedef typename std::iterator_traits::iterator>::value_type value_type; - date_type d1 = from_stream_type(date_string_start, date_string_end, value_type()); - date_string = *(++tok_it); // next token - date_string_start = date_string.begin(), date_string_end = date_string.end(); - date_type d2 = from_stream_type(date_string_start, date_string_end, value_type()); - return period(d1, d2); - } -#endif - -} } //namespace date_time - - - - -#endif - diff --git a/boost/date_time/filetime_functions.hpp b/boost/date_time/filetime_functions.hpp deleted file mode 100644 index f5ef7bf..0000000 --- a/boost/date_time/filetime_functions.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef DATE_TIME_FILETIME_FUNCTIONS_HPP__ -#define DATE_TIME_FILETIME_FUNCTIONS_HPP__ - -/* Copyright (c) 2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -/*! @file filetime_functions.hpp - * Function(s) for converting between a FILETIME structure and a - * time object. This file is only available on systems that have - * BOOST_HAS_FTIME defined. - */ - -#include - -#if defined(BOOST_HAS_FTIME) // skip this file if no FILETIME - -#include -#include -#include - -namespace boost { - -namespace date_time { - -//! Create a time object from an initialized FILETIME struct. -/*! - * Create a time object from an initialized FILETIME struct. - * A FILETIME struct holds 100-nanosecond units (0.0000001). When - * built with microsecond resolution the file_time's sub second value - * will be truncated. Nanosecond resolution has no truncation. - * - * \note The function is templated on the FILETIME type, so that - * it can be used with both native FILETIME and the ad-hoc - * boost::detail::winapi::FILETIME_ type. - */ -template< typename TimeT, typename FileTimeT > -inline -TimeT time_from_ftime(const FileTimeT& ft) -{ - typedef typename TimeT::date_type date_type; - typedef typename TimeT::date_duration_type date_duration_type; - typedef typename TimeT::time_duration_type time_duration_type; - - // https://svn.boost.org/trac/boost/ticket/2523 - // Since this function can be called with arbitrary times, including ones that - // are before 1970-Jan-01, we'll have to cast the time a bit differently, - // than it is done in the microsec_clock::file_time_to_microseconds function. This allows to - // avoid integer wrapping for dates before 1970-Jan-01. - - // 100-nanos since 1601-Jan-01 - uint64_t ft_as_integer = (static_cast< uint64_t >(ft.dwHighDateTime) << 32) | static_cast< uint64_t >(ft.dwLowDateTime); - uint64_t sec = ft_as_integer / 10000000UL; - uint32_t sub_sec = static_cast< uint32_t >(ft_as_integer % 10000000UL) // 100-nanoseconds since the last second -#if !defined(BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG) - / 10U; // microseconds since the last second -#else - * 100U; // nanoseconds since the last second -#endif - - // split sec into usable chunks: days, hours, minutes, & seconds - const uint32_t sec_per_day = 86400; // seconds per day - uint32_t days = static_cast< uint32_t >(sec / sec_per_day); - uint32_t tmp = static_cast< uint32_t >(sec % sec_per_day); - uint32_t hours = tmp / 3600; // sec_per_hour - tmp %= 3600; - uint32_t minutes = tmp / 60; // sec_per_min - tmp %= 60; - uint32_t seconds = tmp; // seconds - - date_duration_type dd(days); - date_type d = date_type(1601, Jan, 01) + dd; - return TimeT(d, time_duration_type(hours, minutes, seconds, sub_sec)); -} - -}} // boost::date_time - -#endif // BOOST_HAS_FTIME - -#endif // DATE_TIME_FILETIME_FUNCTIONS_HPP__ diff --git a/boost/date_time/find_match.hpp b/boost/date_time/find_match.hpp deleted file mode 100644 index 72c81ce..0000000 --- a/boost/date_time/find_match.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _BOOST_DATE_TIME_FIND_MATCH_HPP___ -#define _BOOST_DATE_TIME_FIND_MATCH_HPP___ - -/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include - -namespace boost { -namespace date_time { - - - //! Find index of a string in either of 2 arrays - /*! find_match searches both arrays for a match to 's'. Both arrays - * must contain 'size' elements. The index of the match is returned. - * If no match is found, 'size' is returned. - * Ex. "Jan" returns 0, "Dec" returns 11, "Tue" returns 2. - * 'size' can be sent in with: (greg_month::max)() (which 12), - * (greg_weekday::max)() + 1 (which is 7) or date_time::NumSpecialValues */ - template - short find_match(const charT* const* short_names, - const charT* const* long_names, - short size, - const std::basic_string& s) { - for(short i = 0; i < size; ++i){ - if(short_names[i] == s || long_names[i] == s){ - return i; - } - } - return size; // not-found, return a value out of range - } - - -} } //namespace date_time - - -#endif diff --git a/boost/date_time/format_date_parser.hpp b/boost/date_time/format_date_parser.hpp deleted file mode 100644 index 2269a48..0000000 --- a/boost/date_time/format_date_parser.hpp +++ /dev/null @@ -1,724 +0,0 @@ - -#ifndef DATE_TIME_FORMAT_DATE_PARSER_HPP__ -#define DATE_TIME_FORMAT_DATE_PARSER_HPP__ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - - -#include "boost/lexical_cast.hpp" -#include "boost/date_time/string_parse_tree.hpp" -#include "boost/date_time/strings_from_facet.hpp" -#include "boost/date_time/special_values_parser.hpp" -#include -#include -#include -#include -#ifndef BOOST_NO_STDC_NAMESPACE -# include -#else -# include -#endif - -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::isspace; - using ::isdigit; -} -#endif -namespace boost { namespace date_time { - -//! Helper function for parsing fixed length strings into integers -/*! Will consume 'length' number of characters from stream. Consumed - * character are transfered to parse_match_result struct. - * Returns '-1' if no number can be parsed or incorrect number of - * digits in stream. */ -template -inline -int_type -fixed_string_to_int(std::istreambuf_iterator& itr, - std::istreambuf_iterator& stream_end, - parse_match_result& mr, - unsigned int length, - const charT& fill_char) -{ - //typedef std::basic_string string_type; - unsigned int j = 0; - //string_type s; - while (j < length && itr != stream_end && - (std::isdigit(*itr) || *itr == fill_char)) { - if(*itr == fill_char) { - /* Since a fill_char can be anything, we convert it to a zero. - * lexical_cast will behave predictably when zero is used as fill. */ - mr.cache += ('0'); - } - else { - mr.cache += (*itr); - } - itr++; - j++; - } - int_type i = static_cast(-1); - // mr.cache will hold leading zeros. size() tells us when input is too short. - if(mr.cache.size() < length) { - return i; - } - try { - i = boost::lexical_cast(mr.cache); - }catch(bad_lexical_cast&){ - // we want to return -1 if the cast fails so nothing to do here - } - return i; -} - -//! Helper function for parsing fixed length strings into integers -/*! Will consume 'length' number of characters from stream. Consumed - * character are transfered to parse_match_result struct. - * Returns '-1' if no number can be parsed or incorrect number of - * digits in stream. */ -template -inline -int_type -fixed_string_to_int(std::istreambuf_iterator& itr, - std::istreambuf_iterator& stream_end, - parse_match_result& mr, - unsigned int length) -{ - return fixed_string_to_int(itr, stream_end, mr, length, '0'); -} - -//! Helper function for parsing varied length strings into integers -/*! Will consume 'max_length' characters from stream only if those - * characters are digits. Returns '-1' if no number can be parsed. - * Will not parse a number preceeded by a '+' or '-'. */ -template -inline -int_type -var_string_to_int(std::istreambuf_iterator& itr, - const std::istreambuf_iterator& stream_end, - unsigned int max_length) -{ - typedef std::basic_string string_type; - unsigned int j = 0; - string_type s; - while (itr != stream_end && (j < max_length) && std::isdigit(*itr)) { - s += (*itr); - ++itr; - ++j; - } - int_type i = static_cast(-1); - if(!s.empty()) { - i = boost::lexical_cast(s); - } - return i; -} - - -//! Class with generic date parsing using a format string -/*! The following is the set of recognized format specifiers - - %a - Short weekday name - - %A - Long weekday name - - %b - Abbreviated month name - - %B - Full month name - - %d - Day of the month as decimal 01 to 31 - - %j - Day of year as decimal from 001 to 366 - - %m - Month name as a decimal 01 to 12 - - %U - Week number 00 to 53 with first Sunday as the first day of week 1? - - %w - Weekday as decimal number 0 to 6 where Sunday == 0 - - %W - Week number 00 to 53 where Monday is first day of week 1 - - %x - facet default date representation - - %y - Year without the century - eg: 04 for 2004 - - %Y - Year with century - - The weekday specifiers (%a and %A) do not add to the date construction, - but they provide a way to skip over the weekday names for formats that - provide them. - - todo -- Another interesting feature that this approach could provide is - an option to fill in any missing fields with the current values - from the clock. So if you have %m-%d the parser would detect - the missing year value and fill it in using the clock. - - todo -- What to do with the %x. %x in the classic facet is just bad... - - */ -template -class format_date_parser -{ - public: - typedef std::basic_string string_type; - typedef std::basic_istringstream stringstream_type; - typedef std::istreambuf_iterator stream_itr_type; - typedef typename string_type::const_iterator const_itr; - typedef typename date_type::year_type year_type; - typedef typename date_type::month_type month_type; - typedef typename date_type::day_type day_type; - typedef typename date_type::duration_type duration_type; - typedef typename date_type::day_of_week_type day_of_week_type; - typedef typename date_type::day_of_year_type day_of_year_type; - typedef string_parse_tree parse_tree_type; - typedef typename parse_tree_type::parse_match_result_type match_results; - typedef std::vector > input_collection_type; - - // TODO sv_parser uses its default constructor - write the others - - format_date_parser(const string_type& format_str, - const input_collection_type& month_short_names, - const input_collection_type& month_long_names, - const input_collection_type& weekday_short_names, - const input_collection_type& weekday_long_names) : - m_format(format_str), - m_month_short_names(month_short_names, 1), - m_month_long_names(month_long_names, 1), - m_weekday_short_names(weekday_short_names), - m_weekday_long_names(weekday_long_names) - {} - - format_date_parser(const string_type& format_str, - const std::locale& locale) : - m_format(format_str), - m_month_short_names(gather_month_strings(locale), 1), - m_month_long_names(gather_month_strings(locale, false), 1), - m_weekday_short_names(gather_weekday_strings(locale)), - m_weekday_long_names(gather_weekday_strings(locale, false)) - {} - - format_date_parser(const format_date_parser& fdp) - { - this->m_format = fdp.m_format; - this->m_month_short_names = fdp.m_month_short_names; - this->m_month_long_names = fdp.m_month_long_names; - this->m_weekday_short_names = fdp.m_weekday_short_names; - this->m_weekday_long_names = fdp.m_weekday_long_names; - } - - string_type format() const - { - return m_format; - } - - void format(string_type format_str) - { - m_format = format_str; - } - - void short_month_names(const input_collection_type& month_names) - { - m_month_short_names = parse_tree_type(month_names, 1); - } - void long_month_names(const input_collection_type& month_names) - { - m_month_long_names = parse_tree_type(month_names, 1); - } - void short_weekday_names(const input_collection_type& weekday_names) - { - m_weekday_short_names = parse_tree_type(weekday_names); - } - void long_weekday_names(const input_collection_type& weekday_names) - { - m_weekday_long_names = parse_tree_type(weekday_names); - } - - date_type - parse_date(const string_type& value, - const string_type& format_str, - const special_values_parser& sv_parser) const - { - stringstream_type ss(value); - stream_itr_type sitr(ss); - stream_itr_type stream_end; - return parse_date(sitr, stream_end, format_str, sv_parser); - } - - date_type - parse_date(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - const special_values_parser& sv_parser) const - { - return parse_date(sitr, stream_end, m_format, sv_parser); - } - - /*! Of all the objects that the format_date_parser can parse, only a - * date can be a special value. Therefore, only parse_date checks - * for special_values. */ - date_type - parse_date(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str, - const special_values_parser& sv_parser) const - { - bool use_current_char = false; - - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - short year(0), month(0), day(0), day_of_year(0);// wkday(0); - /* Initialized the following to their minimum values. These intermediate - * objects are used so we get specific exceptions when part of the input - * is unparsable. - * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ - year_type t_year(1400); - month_type t_month(1); - day_type t_day(1); - day_of_week_type wkday(0); - - - const_itr itr(format_str.begin()); - while (itr != format_str.end() && (sitr != stream_end)) { - if (*itr == '%') { - if ( ++itr == format_str.end()) - break; - if (*itr != '%') { - switch(*itr) { - case 'a': - { - //this value is just throw away. It could be used for - //error checking potentially, but it isn't helpful in - //actually constructing the date - we just need to get it - //out of the stream - match_results mr = m_weekday_short_names.match(sitr, stream_end); - if(mr.current_match == match_results::PARSE_ERROR) { - // check special_values - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - wkday = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'A': - { - //this value is just throw away. It could be used for - //error checking potentially, but it isn't helpful in - //actually constructing the date - we just need to get it - //out of the stream - match_results mr = m_weekday_long_names.match(sitr, stream_end); - if(mr.current_match == match_results::PARSE_ERROR) { - // check special_values - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - wkday = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'b': - { - match_results mr = m_month_short_names.match(sitr, stream_end); - if(mr.current_match == match_results::PARSE_ERROR) { - // check special_values - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_month = month_type(mr.current_match); - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'B': - { - match_results mr = m_month_long_names.match(sitr, stream_end); - if(mr.current_match == match_results::PARSE_ERROR) { - // check special_values - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_month = month_type(mr.current_match); - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'd': - { - match_results mr; - day = fixed_string_to_int(sitr, stream_end, mr, 2); - if(day == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_day = day_type(day); - break; - } - case 'e': - { - match_results mr; - day = fixed_string_to_int(sitr, stream_end, mr, 2, ' '); - if(day == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_day = day_type(day); - break; - } - case 'j': - { - match_results mr; - day_of_year = fixed_string_to_int(sitr, stream_end, mr, 3); - if(day_of_year == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - // these next two lines are so we get an exception with bad input - day_of_year_type t_day_of_year(1); - t_day_of_year = day_of_year_type(day_of_year); - break; - } - case 'm': - { - match_results mr; - month = fixed_string_to_int(sitr, stream_end, mr, 2); - if(month == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_month = month_type(month); - break; - } - case 'Y': - { - match_results mr; - year = fixed_string_to_int(sitr, stream_end, mr, 4); - if(year == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - t_year = year_type(year); - break; - } - case 'y': - { - match_results mr; - year = fixed_string_to_int(sitr, stream_end, mr, 2); - if(year == -1) { - if(sv_parser.match(sitr, stream_end, mr)) { - return date_type(static_cast(mr.current_match)); - } - } - year += 2000; //make 2 digit years in this century - t_year = year_type(year); - break; - } - default: - {} //ignore those we don't understand - - }//switch - - } - else { // itr == '%', second consecutive - sitr++; - } - - itr++; //advance past format specifier - } - else { //skip past chars in format and in buffer - itr++; - if (use_current_char) { - use_current_char = false; - } - else { - sitr++; - } - } - } - - if (day_of_year > 0) { - date_type d(static_cast(year-1),12,31); //end of prior year - return d + duration_type(day_of_year); - } - - return date_type(t_year, t_month, t_day); // exceptions were thrown earlier - // if input was no good - } - - //! Throws bad_month if unable to parse - month_type - parse_month(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str) const - { - match_results mr; - return parse_month(sitr, stream_end, format_str, mr); - } - - //! Throws bad_month if unable to parse - month_type - parse_month(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str, - match_results& mr) const - { - bool use_current_char = false; - - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - short month(0); - - const_itr itr(format_str.begin()); - while (itr != format_str.end() && (sitr != stream_end)) { - if (*itr == '%') { - if ( ++itr == format_str.end()) - break; - if (*itr != '%') { - switch(*itr) { - case 'b': - { - mr = m_month_short_names.match(sitr, stream_end); - month = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'B': - { - mr = m_month_long_names.match(sitr, stream_end); - month = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'm': - { - month = var_string_to_int(sitr, stream_end, 2); - // var_string_to_int returns -1 if parse failed. That will - // cause a bad_month exception to be thrown so we do nothing here - break; - } - default: - {} //ignore those we don't understand - - }//switch - - } - else { // itr == '%', second consecutive - sitr++; - } - - itr++; //advance past format specifier - } - else { //skip past chars in format and in buffer - itr++; - if (use_current_char) { - use_current_char = false; - } - else { - sitr++; - } - } - } - - return month_type(month); // throws bad_month exception when values are zero - } - - //! Expects 1 or 2 digits 1-31. Throws bad_day_of_month if unable to parse - day_type - parse_var_day_of_month(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - return day_type(var_string_to_int(sitr, stream_end, 2)); - } - //! Expects 2 digits 01-31. Throws bad_day_of_month if unable to parse - day_type - parse_day_of_month(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - //return day_type(var_string_to_int(sitr, stream_end, 2)); - match_results mr; - return day_type(fixed_string_to_int(sitr, stream_end, mr, 2)); - } - - day_of_week_type - parse_weekday(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str) const - { - match_results mr; - return parse_weekday(sitr, stream_end, format_str, mr); - } - day_of_week_type - parse_weekday(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str, - match_results& mr) const - { - bool use_current_char = false; - - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - short wkday(0); - - const_itr itr(format_str.begin()); - while (itr != format_str.end() && (sitr != stream_end)) { - if (*itr == '%') { - if ( ++itr == format_str.end()) - break; - if (*itr != '%') { - switch(*itr) { - case 'a': - { - //this value is just throw away. It could be used for - //error checking potentially, but it isn't helpful in - //actually constructing the date - we just need to get it - //out of the stream - mr = m_weekday_short_names.match(sitr, stream_end); - wkday = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'A': - { - //this value is just throw away. It could be used for - //error checking potentially, but it isn't helpful in - //actually constructing the date - we just need to get it - //out of the stream - mr = m_weekday_long_names.match(sitr, stream_end); - wkday = mr.current_match; - if (mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'w': - { - // weekday as number 0-6, Sunday == 0 - wkday = var_string_to_int(sitr, stream_end, 2); - break; - } - default: - {} //ignore those we don't understand - - }//switch - - } - else { // itr == '%', second consecutive - sitr++; - } - - itr++; //advance past format specifier - } - else { //skip past chars in format and in buffer - itr++; - if (use_current_char) { - use_current_char = false; - } - else { - sitr++; - } - } - } - - return day_of_week_type(wkday); // throws bad_day_of_month exception - // when values are zero - } - - //! throws bad_year if unable to parse - year_type - parse_year(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str) const - { - match_results mr; - return parse_year(sitr, stream_end, format_str, mr); - } - - //! throws bad_year if unable to parse - year_type - parse_year(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - string_type format_str, - match_results& mr) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - unsigned short year(0); - - const_itr itr(format_str.begin()); - while (itr != format_str.end() && (sitr != stream_end)) { - if (*itr == '%') { - if ( ++itr == format_str.end()) - break; - if (*itr != '%') { - //match_results mr; - switch(*itr) { - case 'Y': - { - // year from 4 digit string - year = fixed_string_to_int(sitr, stream_end, mr, 4); - break; - } - case 'y': - { - // year from 2 digit string (no century) - year = fixed_string_to_int(sitr, stream_end, mr, 2); - year += 2000; //make 2 digit years in this century - break; - } - default: - {} //ignore those we don't understand - - }//switch - - } - else { // itr == '%', second consecutive - sitr++; - } - - itr++; //advance past format specifier - } - else { //skip past chars in format and in buffer - itr++; - sitr++; - } - } - - return year_type(year); // throws bad_year exception when values are zero - } - - - private: - string_type m_format; - parse_tree_type m_month_short_names; - parse_tree_type m_month_long_names; - parse_tree_type m_weekday_short_names; - parse_tree_type m_weekday_long_names; - -}; - -} } //namespace - -#endif - - - diff --git a/boost/date_time/gregorian/conversion.hpp b/boost/date_time/gregorian/conversion.hpp deleted file mode 100644 index c844c4e..0000000 --- a/boost/date_time/gregorian/conversion.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _GREGORIAN__CONVERSION_HPP___ -#define _GREGORIAN__CONVERSION_HPP___ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { - -namespace gregorian { - - //! Converts a date to a tm struct. Throws out_of_range exception if date is a special value - inline - std::tm to_tm(const date& d) - { - if (d.is_special()) - { - std::string s = "tm unable to handle "; - switch (d.as_special()) - { - case date_time::not_a_date_time: - s += "not-a-date-time value"; break; - case date_time::neg_infin: - s += "-infinity date value"; break; - case date_time::pos_infin: - s += "+infinity date value"; break; - default: - s += "a special date value"; break; - } - boost::throw_exception(std::out_of_range(s)); - } - - std::tm datetm; - std::memset(&datetm, 0, sizeof(datetm)); - boost::gregorian::date::ymd_type ymd = d.year_month_day(); - datetm.tm_year = ymd.year - 1900; - datetm.tm_mon = ymd.month - 1; - datetm.tm_mday = ymd.day; - datetm.tm_wday = d.day_of_week(); - datetm.tm_yday = d.day_of_year() - 1; - datetm.tm_isdst = -1; // negative because not enough info to set tm_isdst - return datetm; - } - - //! Converts a tm structure into a date dropping the any time values. - inline - date date_from_tm(const std::tm& datetm) - { - return date(static_cast(datetm.tm_year+1900), - static_cast(datetm.tm_mon+1), - static_cast(datetm.tm_mday)); - } - -} } //namespace boost::gregorian - -#endif diff --git a/boost/date_time/gregorian/formatters.hpp b/boost/date_time/gregorian/formatters.hpp deleted file mode 100644 index 1222b59..0000000 --- a/boost/date_time/gregorian/formatters.hpp +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef GREGORIAN_FORMATTERS_HPP___ -#define GREGORIAN_FORMATTERS_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/compiler_config.hpp" -#include "boost/date_time/gregorian/gregorian_types.hpp" -#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) -#include "boost/date_time/date_formatting_limited.hpp" -#else -#include "boost/date_time/date_formatting.hpp" -#endif -#include "boost/date_time/iso_format.hpp" -#include "boost/date_time/date_format_simple.hpp" - -/* NOTE: "to_*_string" code for older compilers, ones that define - * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in - * formatters_limited.hpp - */ - -namespace boost { -namespace gregorian { - - // wrapper function for to_simple_(w)string(date) - template - inline - std::basic_string to_simple_string_type(const date& d) { - return date_time::date_formatter,charT>::date_to_string(d); - } - //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 - /*!\ingroup date_format - */ - inline std::string to_simple_string(const date& d) { - return to_simple_string_type(d); - } - - - // wrapper function for to_simple_(w)string(date_period) - template - inline std::basic_string to_simple_string_type(const date_period& d) { - typedef std::basic_string string_type; - charT b = '[', m = '/', e=']'; - - string_type d1(date_time::date_formatter,charT>::date_to_string(d.begin())); - string_type d2(date_time::date_formatter,charT>::date_to_string(d.last())); - return string_type(b + d1 + m + d2 + e); - } - //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] - /*!\ingroup date_format - */ - inline std::string to_simple_string(const date_period& d) { - return to_simple_string_type(d); - } - - // wrapper function for to_iso_(w)string(date_period) - template - inline std::basic_string to_iso_string_type(const date_period& d) { - charT sep = '/'; - std::basic_string s(date_time::date_formatter,charT>::date_to_string(d.begin())); - return s + sep + date_time::date_formatter,charT>::date_to_string(d.last()); - } - //! Date period to ISO 8601 standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 - /*!\ingroup date_format - */ - inline std::string to_iso_string(const date_period& d) { - return to_iso_string_type(d); - } - - - // wrapper function for to_iso_extended_(w)string(date) - template - inline std::basic_string to_iso_extended_string_type(const date& d) { - return date_time::date_formatter,charT>::date_to_string(d); - } - //! Convert to ISO 8601 extended format string CCYY-MM-DD. Example 2002-12-31 - /*!\ingroup date_format - */ - inline std::string to_iso_extended_string(const date& d) { - return to_iso_extended_string_type(d); - } - - // wrapper function for to_iso_(w)string(date) - template - inline std::basic_string to_iso_string_type(const date& d) { - return date_time::date_formatter,charT>::date_to_string(d); - } - //! Convert to ISO 8601 standard string YYYYMMDD. Example: 20021231 - /*!\ingroup date_format - */ - inline std::string to_iso_string(const date& d) { - return to_iso_string_type(d); - } - - - - - // wrapper function for to_sql_(w)string(date) - template - inline std::basic_string to_sql_string_type(const date& d) - { - date::ymd_type ymd = d.year_month_day(); - std::basic_ostringstream ss; - ss << ymd.year << "-" - << std::setw(2) << std::setfill(ss.widen('0')) - << ymd.month.as_number() //solves problem with gcc 3.1 hanging - << "-" - << std::setw(2) << std::setfill(ss.widen('0')) - << ymd.day; - return ss.str(); - } - inline std::string to_sql_string(const date& d) { - return to_sql_string_type(d); - } - - -#if !defined(BOOST_NO_STD_WSTRING) - //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] - /*!\ingroup date_format - */ - inline std::wstring to_simple_wstring(const date_period& d) { - return to_simple_string_type(d); - } - //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 - /*!\ingroup date_format - */ - inline std::wstring to_simple_wstring(const date& d) { - return to_simple_string_type(d); - } - //! Date period to iso standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 - /*!\ingroup date_format - */ - inline std::wstring to_iso_wstring(const date_period& d) { - return to_iso_string_type(d); - } - //! Convert to iso extended format string CCYY-MM-DD. Example 2002-12-31 - /*!\ingroup date_format - */ - inline std::wstring to_iso_extended_wstring(const date& d) { - return to_iso_extended_string_type(d); - } - //! Convert to iso standard string YYYYMMDD. Example: 20021231 - /*!\ingroup date_format - */ - inline std::wstring to_iso_wstring(const date& d) { - return to_iso_string_type(d); - } - inline std::wstring to_sql_wstring(const date& d) { - return to_sql_string_type(d); - } -#endif // BOOST_NO_STD_WSTRING - -} } //namespace gregorian - - -#endif - diff --git a/boost/date_time/gregorian/formatters_limited.hpp b/boost/date_time/gregorian/formatters_limited.hpp deleted file mode 100644 index 1763b20..0000000 --- a/boost/date_time/gregorian/formatters_limited.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef GREGORIAN_FORMATTERS_LIMITED_HPP___ -#define GREGORIAN_FORMATTERS_LIMITED_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/gregorian/gregorian_types.hpp" -#include "boost/date_time/date_formatting_limited.hpp" -#include "boost/date_time/iso_format.hpp" -#include "boost/date_time/date_format_simple.hpp" -#include "boost/date_time/compiler_config.hpp" - -namespace boost { -namespace gregorian { - - //! To YYYY-mmm-DD string where mmm 3 char month name. Example: 2002-Jan-01 - /*!\ingroup date_format - */ - inline std::string to_simple_string(const date& d) { - return date_time::date_formatter >::date_to_string(d); - } - - //! Convert date period to simple string. Example: [2002-Jan-01/2002-Jan-02] - /*!\ingroup date_format - */ - inline std::string to_simple_string(const date_period& d) { - std::string s("["); - std::string d1(date_time::date_formatter >::date_to_string(d.begin())); - std::string d2(date_time::date_formatter >::date_to_string(d.last())); - return std::string("[" + d1 + "/" + d2 + "]"); - } - - //! Date period to ISO 8601 standard format CCYYMMDD/CCYYMMDD. Example: 20021225/20021231 - /*!\ingroup date_format - */ - inline std::string to_iso_string(const date_period& d) { - std::string s(date_time::date_formatter >::date_to_string(d.begin())); - return s + "/" + date_time::date_formatter >::date_to_string(d.last()); - } - - - //! Convert to ISO 8601 extended format string CCYY-MM-DD. Example 2002-12-31 - /*!\ingroup date_format - */ - inline std::string to_iso_extended_string(const date& d) { - return date_time::date_formatter >::date_to_string(d); - } - - //! Convert to ISO 8601 standard string YYYYMMDD. Example: 20021231 - /*!\ingroup date_format - */ - inline std::string to_iso_string(const date& d) { - return date_time::date_formatter >::date_to_string(d); - } - - - - inline std::string to_sql_string(const date& d) - { - date::ymd_type ymd = d.year_month_day(); - std::ostringstream ss; - ss << ymd.year << "-" - << std::setw(2) << std::setfill('0') - << ymd.month.as_number() //solves problem with gcc 3.1 hanging - << "-" - << std::setw(2) << std::setfill('0') - << ymd.day; - return ss.str(); - } - - -} } //namespace gregorian - - -#endif - diff --git a/boost/date_time/gregorian/greg_facet.hpp b/boost/date_time/gregorian/greg_facet.hpp deleted file mode 100644 index 5352df1..0000000 --- a/boost/date_time/gregorian/greg_facet.hpp +++ /dev/null @@ -1,374 +0,0 @@ -#ifndef GREGORIAN_FACET_HPP___ -#define GREGORIAN_FACET_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include // sets BOOST_DATE_TIME_NO_LOCALE -#include -#include - -//This file is basically commented out if locales are not supported -#ifndef BOOST_DATE_TIME_NO_LOCALE - -#include -#include -#include -#include -#include - -namespace boost { -namespace gregorian { - - //! Configuration of the output facet template - struct BOOST_SYMBOL_VISIBLE greg_facet_config - { - typedef boost::gregorian::greg_month month_type; - typedef boost::date_time::special_values special_value_enum; - typedef boost::gregorian::months_of_year month_enum; - typedef boost::date_time::weekdays weekday_enum; - }; - -#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) - //! Create the base facet type for gregorian::date - typedef boost::date_time::date_names_put greg_base_facet; - - //! ostream operator for gregorian::date - /*! Uses the date facet to determine various output parameters including: - * - string values for the month (eg: Jan, Feb, Mar) (default: English) - * - string values for special values (eg: not-a-date-time) (default: English) - * - selection of long, short strings, or numerical month representation (default: short string) - * - month day year order (default yyyy-mmm-dd) - */ - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const date& d) - { - typedef boost::date_time::date_names_put facet_def; - typedef boost::date_time::ostream_date_formatter greg_ostream_formatter; - greg_ostream_formatter::date_put(d, os); - return os; - } - - //! operator<< for gregorian::greg_month typically streaming: Jan, Feb, Mar... - /*! Uses the date facet to determine output string as well as selection of long or short strings. - * Default if no facet is installed is to output a 2 wide numeric value for the month - * eg: 01 == Jan, 02 == Feb, ... 12 == Dec. - */ - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const greg_month& m) - { - typedef boost::date_time::date_names_put facet_def; - typedef boost::date_time::ostream_month_formatter greg_month_formatter; - std::locale locale = os.getloc(); - if (std::has_facet(locale)) { - const facet_def& f = std::use_facet(locale); - greg_month_formatter::format_month(m, os, f); - - } - else { // default to numeric - boost::io::basic_ios_fill_saver ifs(os); - os << std::setw(2) << std::setfill(os.widen('0')) << m.as_number(); - } - - return os; - } - - //! operator<< for gregorian::greg_weekday typically streaming: Sun, Mon, Tue, ... - /*! Uses the date facet to determine output string as well as selection of long or short string. - * Default if no facet is installed is to output a 3 char english string for the - * day of the week. - */ - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const greg_weekday& wd) - { - typedef boost::date_time::date_names_put facet_def; - typedef boost::date_time::ostream_weekday_formatter greg_weekday_formatter; - std::locale locale = os.getloc(); - if (std::has_facet(locale)) { - const facet_def& f = std::use_facet(locale); - greg_weekday_formatter::format_weekday(wd, os, f, true); - } - else { //default to short English string eg: Sun, Mon, Tue, Wed... - os << wd.as_short_string(); - } - - return os; - } - - //! operator<< for gregorian::date_period typical output: [2002-Jan-01/2002-Jan-31] - /*! Uses the date facet to determine output string as well as selection of long - * or short string fr dates. - * Default if no facet is installed is to output a 3 char english string for the - * day of the week. - */ - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const date_period& dp) - { - os << '['; //TODO: facet or manipulator for periods? - os << dp.begin(); - os << '/'; //TODO: facet or manipulator for periods? - os << dp.last(); - os << ']'; - return os; - } - - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const date_duration& dd) - { - //os << dd.days(); - os << dd.get_rep(); - return os; - } - - //! operator<< for gregorian::partial_date. Output: "Jan 1" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const partial_date& pd) - { - boost::io::basic_ios_fill_saver ifs(os); - os << std::setw(2) << std::setfill(os.widen('0')) << pd.day() << ' ' - << pd.month().as_short_string() ; - return os; - } - - //! operator<< for gregorian::nth_kday_of_month. Output: "first Mon of Jun" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const nth_kday_of_month& nkd) - { - os << nkd.nth_week_as_str() << ' ' - << nkd.day_of_week() << " of " - << nkd.month().as_short_string() ; - return os; - } - - //! operator<< for gregorian::first_kday_of_month. Output: "first Mon of Jun" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const first_kday_of_month& fkd) - { - os << "first " << fkd.day_of_week() << " of " - << fkd.month().as_short_string() ; - return os; - } - - //! operator<< for gregorian::last_kday_of_month. Output: "last Mon of Jun" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const last_kday_of_month& lkd) - { - os << "last " << lkd.day_of_week() << " of " - << lkd.month().as_short_string() ; - return os; - } - - //! operator<< for gregorian::first_kday_after. Output: "first Mon after" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const first_kday_after& fka) - { - os << fka.day_of_week() << " after"; - return os; - } - - //! operator<< for gregorian::first_kday_before. Output: "first Mon before" - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const first_kday_before& fkb) - { - os << fkb.day_of_week() << " before"; - return os; - } -#endif // USE_DATE_TIME_PRE_1_33_FACET_IO - /**************** Input Streaming ******************/ - -#if !defined(BOOST_NO_STD_ITERATOR_TRAITS) - //! operator>> for gregorian::date - template - inline - std::basic_istream& operator>>(std::basic_istream& is, date& d) - { - std::istream_iterator, charT> beg(is), eos; - d = from_stream(beg, eos); - return is; - } -#endif // BOOST_NO_STD_ITERATOR_TRAITS - - //! operator>> for gregorian::date_duration - template - inline - std::basic_istream& operator>>(std::basic_istream& is, - date_duration& dd) - { - long v; - is >> v; - dd = date_duration(v); - return is; - } - - //! operator>> for gregorian::date_period - template - inline - std::basic_istream& operator>>(std::basic_istream& is, - date_period& dp) - { - std::basic_string s; - is >> s; - dp = date_time::from_simple_string_type(s); - return is; - } - - //! generates a locale with the set of gregorian name-strings of type char* - BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, char type); - - //! Returns a pointer to a facet with a default set of names (English) - /* Necessary in the event an exception is thrown from op>> for - * weekday or month. See comments in those functions for more info */ - BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put* create_facet_def(char type); - -#ifndef BOOST_NO_STD_WSTRING - //! generates a locale with the set of gregorian name-strings of type wchar_t* - BOOST_DATE_TIME_DECL std::locale generate_locale(std::locale& loc, wchar_t type); - //! Returns a pointer to a facet with a default set of names (English) - /* Necessary in the event an exception is thrown from op>> for - * weekday or month. See comments in those functions for more info */ - BOOST_DATE_TIME_DECL boost::date_time::all_date_names_put* create_facet_def(wchar_t type); -#endif // BOOST_NO_STD_WSTRING - - //! operator>> for gregorian::greg_month - throws exception if invalid month given - template - inline - std::basic_istream& operator>>(std::basic_istream& is,greg_month& m) - { - typedef boost::date_time::all_date_names_put facet_def; - - std::basic_string s; - is >> s; - - if(!std::has_facet(is.getloc())) { - std::locale loc = is.getloc(); - charT a = '\0'; - is.imbue(generate_locale(loc, a)); - } - - short num = 0; - - try{ - const facet_def& f = std::use_facet(is.getloc()); - num = date_time::find_match(f.get_short_month_names(), - f.get_long_month_names(), - (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size, - // which is needed by find_match - } - /* bad_cast will be thrown if the desired facet is not accessible - * so we can generate the facet. This has the drawback of using english - * names as a default. */ - catch(std::bad_cast&){ - charT a = '\0'; - -#if defined(BOOST_NO_CXX11_SMART_PTR) - - std::auto_ptr< const facet_def > f(create_facet_def(a)); - -#else - - std::unique_ptr< const facet_def > f(create_facet_def(a)); - -#endif - - num = date_time::find_match(f->get_short_month_names(), - f->get_long_month_names(), - (greg_month::max)(), s); // greg_month spans 1..12, so max returns the array size, - // which is needed by find_match - } - - ++num; // months numbered 1-12 - m = greg_month(num); - - return is; - } - - //! operator>> for gregorian::greg_weekday - throws exception if invalid weekday given - template - inline - std::basic_istream& operator>>(std::basic_istream& is,greg_weekday& wd) - { - typedef boost::date_time::all_date_names_put facet_def; - - std::basic_string s; - is >> s; - - if(!std::has_facet(is.getloc())) { - std::locale loc = is.getloc(); - charT a = '\0'; - is.imbue(generate_locale(loc, a)); - } - - short num = 0; - try{ - const facet_def& f = std::use_facet(is.getloc()); - num = date_time::find_match(f.get_short_weekday_names(), - f.get_long_weekday_names(), - (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed - // to form the array size which is needed by find_match - } - /* bad_cast will be thrown if the desired facet is not accessible - * so we can generate the facet. This has the drawback of using english - * names as a default. */ - catch(std::bad_cast&){ - charT a = '\0'; - -#if defined(BOOST_NO_CXX11_SMART_PTR) - - std::auto_ptr< const facet_def > f(create_facet_def(a)); - -#else - - std::unique_ptr< const facet_def > f(create_facet_def(a)); - -#endif - - num = date_time::find_match(f->get_short_weekday_names(), - f->get_long_weekday_names(), - (greg_weekday::max)() + 1, s); // greg_weekday spans 0..6, so increment is needed - // to form the array size which is needed by find_match - } - - wd = greg_weekday(num); // weekdays numbered 0-6 - return is; - } - -} } //namespace gregorian - -#endif - -#endif - diff --git a/boost/date_time/gregorian/gregorian.hpp b/boost/date_time/gregorian/gregorian.hpp deleted file mode 100644 index 47d545e..0000000 --- a/boost/date_time/gregorian/gregorian.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef GREGORIAN_HPP__ -#define GREGORIAN_HPP__ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -/*! @file gregorian.hpp - Single file header that provides overall include for all elements of - the gregorian date-time system. This includes the various types - defined, but also other functions for formatting and parsing. -*/ - - -#include "boost/date_time/compiler_config.hpp" -#include "boost/date_time/gregorian/gregorian_types.hpp" -#include "boost/date_time/gregorian/conversion.hpp" -#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) -#include "boost/date_time/gregorian/formatters_limited.hpp" -#else -#include "boost/date_time/gregorian/formatters.hpp" -#endif - -#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) -#include "boost/date_time/gregorian/greg_facet.hpp" -#else -#include "boost/date_time/gregorian/gregorian_io.hpp" -#endif // USE_DATE_TIME_PRE_1_33_FACET_IO - -#include "boost/date_time/gregorian/parsers.hpp" - - - -#endif diff --git a/boost/date_time/gregorian/gregorian_io.hpp b/boost/date_time/gregorian/gregorian_io.hpp deleted file mode 100644 index 49e5d41..0000000 --- a/boost/date_time/gregorian/gregorian_io.hpp +++ /dev/null @@ -1,784 +0,0 @@ -#ifndef DATE_TIME_GREGORIAN_IO_HPP__ -#define DATE_TIME_GREGORIAN_IO_HPP__ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include // i/ostreambuf_iterator -#include -#include -#include -#include -#include -#include -#include -#include // to_tm will be needed in the facets - -namespace boost { -namespace gregorian { - - - typedef boost::date_time::period_formatter wperiod_formatter; - typedef boost::date_time::period_formatter period_formatter; - - typedef boost::date_time::date_facet wdate_facet; - typedef boost::date_time::date_facet date_facet; - - typedef boost::date_time::period_parser period_parser; - typedef boost::date_time::period_parser wperiod_parser; - - typedef boost::date_time::special_values_formatter special_values_formatter; - typedef boost::date_time::special_values_formatter wspecial_values_formatter; - - typedef boost::date_time::special_values_parser special_values_parser; - typedef boost::date_time::special_values_parser wspecial_values_parser; - - typedef boost::date_time::date_input_facet date_input_facet; - typedef boost::date_time::date_input_facet wdate_input_facet; - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::date& d) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), d); - else { - //instantiate a custom facet for dealing with dates since the user - //has not put one in the stream so far. This is for efficiency - //since we would always need to reconstruct for every date - //if the locale did not already exist. Of course this will be overridden - //if the user imbues at some later point. With the default settings - //for the facet the resulting format will be the same as the - //std::time_facet settings. - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), d); - } - return os; - } - - //! input operator for date - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, date& d) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, d); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, d); - } - } - catch(...) { - // mask tells us what exceptions are turned on - std::ios_base::iostate exception_mask = is.exceptions(); - // if the user wants exceptions on failbit, we'll rethrow our - // date_time exception & set the failbit - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} // ignore this one - throw; // rethrow original exception - } - else { - // if the user want's to fail quietly, we simply set the failbit - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::date_duration& dd) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), dd); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), dd); - - } - return os; - } - - //! input operator for date_duration - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, date_duration& dd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, dd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, dd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::date_period& dp) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), dp); - else { - //instantiate a custom facet for dealing with date periods since the user - //has not put one in the stream so far. This is for efficiency - //since we would always need to reconstruct for every time period - //if the local did not already exist. Of course this will be overridden - //if the user imbues at some later point. With the default settings - //for the facet the resulting format will be the same as the - //std::time_facet settings. - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), dp); - - } - return os; - } - - //! input operator for date_period - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, date_period& dp) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, dp); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, dp); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - /********** small gregorian types **********/ - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::greg_month& gm) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), gm); - else { - custom_date_facet* f = new custom_date_facet();//-> 10/1074199752/32 because year & day not initialized in put(...) - //custom_date_facet* f = new custom_date_facet("%B"); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), gm); - } - return os; - } - - //! input operator for greg_month - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, greg_month& m) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, m); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, m); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::greg_weekday& gw) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), gw); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), gw); - } - return os; - } - - //! input operator for greg_weekday - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, greg_weekday& wd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, wd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, wd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - //NOTE: output operator for greg_day was not necessary - - //! input operator for greg_day - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, greg_day& gd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, gd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, gd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - //NOTE: output operator for greg_year was not necessary - - //! input operator for greg_year - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, greg_year& gy) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, gy); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, gy); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - /********** date generator types **********/ - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::partial_date& pd) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), pd); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), pd); - } - return os; - } - - //! input operator for partial_date - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, partial_date& pd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, pd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, pd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::nth_day_of_the_week_in_month& nkd) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), nkd); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), nkd); - } - return os; - } - - //! input operator for nth_day_of_the_week_in_month - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, - nth_day_of_the_week_in_month& nday) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, nday); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, nday); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_in_month& fkd) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fkd); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), fkd); - } - return os; - } - - //! input operator for first_day_of_the_week_in_month - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, - first_day_of_the_week_in_month& fkd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, fkd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, fkd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::last_day_of_the_week_in_month& lkd) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), lkd); - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), lkd); - } - return os; - } - - //! input operator for last_day_of_the_week_in_month - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, - last_day_of_the_week_in_month& lkd) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, lkd); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, lkd); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_after& fda) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) { - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fda); - } - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), fda); - } - return os; - } - - //! input operator for first_day_of_the_week_after - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, - first_day_of_the_week_after& fka) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, fka); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, fka); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - - template - inline std::basic_ostream& - operator<<(std::basic_ostream& os, const boost::gregorian::first_day_of_the_week_before& fdb) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::date_facet custom_date_facet; - std::ostreambuf_iterator output_itr(os); - if (std::has_facet(os.getloc())) { - std::use_facet(os.getloc()).put(output_itr, os, os.fill(), fdb); - } - else { - custom_date_facet* f = new custom_date_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(output_itr, os, os.fill(), fdb); - } - return os; - } - - //! input operator for first_day_of_the_week_before - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, - first_day_of_the_week_before& fkb) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::date_input_facet date_input_facet_local; - - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, fkb); - } - else { - date_input_facet_local* f = new date_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, fkb); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - - } - } - return is; - } - - -} } // namespaces - -#endif // DATE_TIME_GREGORIAN_IO_HPP__ diff --git a/boost/date_time/gregorian/parsers.hpp b/boost/date_time/gregorian/parsers.hpp deleted file mode 100644 index d603b6a..0000000 --- a/boost/date_time/gregorian/parsers.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef GREGORIAN_PARSERS_HPP___ -#define GREGORIAN_PARSERS_HPP___ - -/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace gregorian { - - //! Return special_value from string argument - /*! Return special_value from string argument. If argument is - * not one of the special value names (defined in names.hpp), - * return 'not_special' */ - inline - date_time::special_values - special_value_from_string(const std::string& s) { - static const char* const special_value_names[date_time::NumSpecialValues] - = {"not-a-date-time","-infinity","+infinity","min_date_time", - "max_date_time","not_special"}; - - short i = date_time::find_match(special_value_names, - special_value_names, - date_time::NumSpecialValues, - s); - if(i >= date_time::NumSpecialValues) { // match not found - return date_time::not_special; - } - else { - return static_cast(i); - } - } - - //! Deprecated: Use from_simple_string - inline date from_string(const std::string& s) { - return date_time::parse_date(s); - } - - //! From delimited date string where with order year-month-day eg: 2002-1-25 or 2003-Jan-25 (full month name is also accepted) - inline date from_simple_string(const std::string& s) { - return date_time::parse_date(s, date_time::ymd_order_iso); - } - - //! From delimited date string where with order year-month-day eg: 1-25-2003 or Jan-25-2003 (full month name is also accepted) - inline date from_us_string(const std::string& s) { - return date_time::parse_date(s, date_time::ymd_order_us); - } - - //! From delimited date string where with order day-month-year eg: 25-1-2002 or 25-Jan-2003 (full month name is also accepted) - inline date from_uk_string(const std::string& s) { - return date_time::parse_date(s, date_time::ymd_order_dmy); - } - - //! From ISO 8601 type date string where with order year-month-day eg: 20020125 - inline date from_undelimited_string(const std::string& s) { - return date_time::parse_undelimited_date(s); - } - - //! From ISO 8601 type date string where with order year-month-day eg: 20020125 - inline date date_from_iso_string(const std::string& s) { - return date_time::parse_undelimited_date(s); - } - -#if !(defined(BOOST_NO_STD_ITERATOR_TRAITS)) - //! Stream should hold a date in the form of: 2002-1-25. Month number, abbrev, or name are accepted - /* Arguments passed in by-value for convertability of char[] - * to iterator_type. Calls to from_stream_type are by-reference - * since conversion is already done */ - template - inline date from_stream(iterator_type beg, iterator_type end) { - if(beg == end) - { - return date(not_a_date_time); - } - typedef typename std::iterator_traits::value_type value_type; - return date_time::from_stream_type(beg, end, value_type()); - } -#endif //BOOST_NO_STD_ITERATOR_TRAITS - -#if (defined(_MSC_VER) && (_MSC_VER < 1300)) - // This function cannot be compiled with MSVC 6.0 due to internal compiler shorcomings -#else - //! Function to parse a date_period from a string (eg: [2003-Oct-31/2003-Dec-25]) - inline date_period date_period_from_string(const std::string& s){ - return date_time::from_simple_string_type(s); - } -# if !defined(BOOST_NO_STD_WSTRING) - //! Function to parse a date_period from a wstring (eg: [2003-Oct-31/2003-Dec-25]) - inline date_period date_period_from_wstring(const std::wstring& s){ - return date_time::from_simple_string_type(s); - } -# endif // BOOST_NO_STD_WSTRING -#endif - -} } //namespace gregorian - -#endif diff --git a/boost/date_time/iso_format.hpp b/boost/date_time/iso_format.hpp deleted file mode 100644 index 9942a22..0000000 --- a/boost/date_time/iso_format.hpp +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef ISO_FORMAT_HPP___ -#define ISO_FORMAT_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/parse_format_base.hpp" - -namespace boost { -namespace date_time { - -//! Class to provide common ISO 8601 formatting spec -template -class iso_format_base { -public: - //! Describe month format -- its an integer in ISO 8601 format - static month_format_spec month_format() - { - return month_as_integer; - } - - //! String used printed is date is invalid - static const charT* not_a_date() - { - return "not-a-date-time"; - } - //! String used to for positive infinity value - static const charT* pos_infinity() - { - return "+infinity"; - } - //! String used to for positive infinity value - static const charT* neg_infinity() - { - return "-infinity"; - } - - //! ISO 8601 char for a year -- used in durations - static charT year_sep_char() - { - return 'Y'; - } - //! ISO 8601 char for a month - static charT month_sep_char() - { - return '-'; - } - //! ISO 8601 char for a day - static charT day_sep_char() - { - return '-'; - } - //! char for minute - static charT hour_sep_char() - { - return ':'; - } - //! char for minute - static charT minute_sep_char() - { - return ':'; - } - //! char for second - static charT second_sep_char() - { - return ':'; - } - //! ISO 8601 char for a period - static charT period_start_char() - { - return 'P'; - } - //! Used in time in mixed strings to set start of time - static charT time_start_char() - { - return 'T'; - } - - //! Used in mixed strings to identify start of a week number - static charT week_start_char() - { - return 'W'; - } - - //! Separators for periods - static charT period_sep_char() - { - return '/'; - } - //! Separator for hh:mm:ss - static charT time_sep_char() - { - return ':'; - } - //! Preferred Separator for hh:mm:ss,decimal_fraction - static charT fractional_time_sep_char() - { - return ','; - } - - static bool is_component_sep(charT sep) - { - switch(sep) { - case 'H': - case 'M': - case 'S': - case 'W': - case 'T': - case 'Y': - case 'D':return true; - default: - return false; - } - } - - static bool is_fractional_time_sep(charT sep) - { - switch(sep) { - case ',': - case '.': return true; - default: return false; - } - } - static bool is_timezone_sep(charT sep) - { - switch(sep) { - case '+': - case '-': return true; - default: return false; - } - } - static charT element_sep_char() - { - return '-'; - } - -}; - -#ifndef BOOST_NO_STD_WSTRING - -//! Class to provide common ISO 8601 formatting spec -template<> -class iso_format_base { -public: - //! Describe month format -- its an integer in ISO 8601 format - static month_format_spec month_format() - { - return month_as_integer; - } - - //! String used printed is date is invalid - static const wchar_t* not_a_date() - { - return L"not-a-date-time"; - } - //! String used to for positive infinity value - static const wchar_t* pos_infinity() - { - return L"+infinity"; - } - //! String used to for positive infinity value - static const wchar_t* neg_infinity() - { - return L"-infinity"; - } - - //! ISO 8601 char for a year -- used in durations - static wchar_t year_sep_char() - { - return 'Y'; - } - //! ISO 8601 char for a month - static wchar_t month_sep_char() - { - return '-'; - } - //! ISO 8601 char for a day - static wchar_t day_sep_char() - { - return '-'; - } - //! char for minute - static wchar_t hour_sep_char() - { - return ':'; - } - //! char for minute - static wchar_t minute_sep_char() - { - return ':'; - } - //! char for second - static wchar_t second_sep_char() - { - return ':'; - } - //! ISO 8601 char for a period - static wchar_t period_start_char() - { - return 'P'; - } - //! Used in time in mixed strings to set start of time - static wchar_t time_start_char() - { - return 'T'; - } - - //! Used in mixed strings to identify start of a week number - static wchar_t week_start_char() - { - return 'W'; - } - - //! Separators for periods - static wchar_t period_sep_char() - { - return '/'; - } - //! Separator for hh:mm:ss - static wchar_t time_sep_char() - { - return ':'; - } - //! Preferred Separator for hh:mm:ss,decimal_fraction - static wchar_t fractional_time_sep_char() - { - return ','; - } - - static bool is_component_sep(wchar_t sep) - { - switch(sep) { - case 'H': - case 'M': - case 'S': - case 'W': - case 'T': - case 'Y': - case 'D':return true; - default: - return false; - } - } - - static bool is_fractional_time_sep(wchar_t sep) - { - switch(sep) { - case ',': - case '.': return true; - default: return false; - } - } - static bool is_timezone_sep(wchar_t sep) - { - switch(sep) { - case '+': - case '-': return true; - default: return false; - } - } - static wchar_t element_sep_char() - { - return '-'; - } - -}; - -#endif // BOOST_NO_STD_WSTRING - -//! Format description for ISO 8601 normal YYYYMMDD -template -class iso_format : public iso_format_base { -public: - //! The ios standard format doesn't use char separators - static bool has_date_sep_chars() - { - return false; - } -}; - -//! Extended format uses seperators YYYY-MM-DD -template -class iso_extended_format : public iso_format_base { -public: - //! Extended format needs char separators - static bool has_date_sep_chars() - { - return true; - } - -}; - -} } //namespace date_time - - - - -#endif diff --git a/boost/date_time/parse_format_base.hpp b/boost/date_time/parse_format_base.hpp deleted file mode 100644 index d4b2f59..0000000 --- a/boost/date_time/parse_format_base.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef DATE_TIME_PARSE_FORMAT_BASE__ -#define DATE_TIME_PARSE_FORMAT_BASE__ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland - * $Date$ - */ - -namespace boost { -namespace date_time { - - //! Enum for distinguishing parsing and formatting options - enum month_format_spec {month_as_integer, month_as_short_string, - month_as_long_string}; - - //! Enum for distinguishing the order of Month, Day, & Year. - /*! Enum for distinguishing the order in which Month, Day, & Year - * will appear in a date string */ - enum ymd_order_spec {ymd_order_iso, //order is year-month-day - ymd_order_dmy, //day-month-year - ymd_order_us}; //order is month-day-year - - -} }//namespace date_time - -#endif diff --git a/boost/date_time/period_formatter.hpp b/boost/date_time/period_formatter.hpp deleted file mode 100644 index 2b46c3a..0000000 --- a/boost/date_time/period_formatter.hpp +++ /dev/null @@ -1,200 +0,0 @@ - -#ifndef DATETIME_PERIOD_FORMATTER_HPP___ -#define DATETIME_PERIOD_FORMATTER_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include - -namespace boost { namespace date_time { - - - //! Not a facet, but a class used to specify and control period formats - /*! Provides settings for the following: - * - period_separator -- default '/' - * - period_open_start_delimeter -- default '[' - * - period_open_range_end_delimeter -- default ')' - * - period_closed_range_end_delimeter -- default ']' - * - display_as_open_range, display_as_closed_range -- default closed_range - * - * Thus the default formatting for a period is as follows: - *@code - * [period.start()/period.last()] - *@endcode - * So for a typical date_period this would be - *@code - * [2004-Jan-04/2004-Feb-01] - *@endcode - * where the date formatting is controlled by the date facet - */ - template > > - class period_formatter { - public: - typedef std::basic_string string_type; - typedef CharT char_type; - typedef typename std::basic_string::const_iterator const_itr_type; - typedef std::vector > collection_type; - - static const char_type default_period_separator[2]; - static const char_type default_period_start_delimeter[2]; - static const char_type default_period_open_range_end_delimeter[2]; - static const char_type default_period_closed_range_end_delimeter[2]; - - enum range_display_options { AS_OPEN_RANGE, AS_CLOSED_RANGE }; - - //! Constructor that sets up period formatter options -- default should suffice most cases. - period_formatter(range_display_options range_option_in = AS_CLOSED_RANGE, - const char_type* const period_separator = default_period_separator, - const char_type* const period_start_delimeter = default_period_start_delimeter, - const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, - const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) : - m_range_option(range_option_in), - m_period_separator(period_separator), - m_period_start_delimeter(period_start_delimeter), - m_open_range_end_delimeter(period_open_range_end_delimeter), - m_closed_range_end_delimeter(period_closed_range_end_delimeter) - {} - - //! Puts the characters between period elements into stream -- default is / - OutItrT put_period_separator(OutItrT& oitr) const - { - const_itr_type ci = m_period_separator.begin(); - while (ci != m_period_separator.end()) { - *oitr = *ci; - ci++; - } - return oitr; - } - - //! Puts the period start characters into stream -- default is [ - OutItrT put_period_start_delimeter(OutItrT& oitr) const - { - const_itr_type ci = m_period_start_delimeter.begin(); - while (ci != m_period_start_delimeter.end()) { - *oitr = *ci; - ci++; - } - return oitr; - } - - //! Puts the period end characters into stream as controled by open/closed range setting. - OutItrT put_period_end_delimeter(OutItrT& oitr) const - { - - const_itr_type ci, end; - if (m_range_option == AS_OPEN_RANGE) { - ci = m_open_range_end_delimeter.begin(); - end = m_open_range_end_delimeter.end(); - } - else { - ci = m_closed_range_end_delimeter.begin(); - end = m_closed_range_end_delimeter.end(); - } - while (ci != end) { - *oitr = *ci; - ci++; - } - return oitr; - } - - range_display_options range_option() const - { - return m_range_option; - } - - //! Reset the range_option control - void - range_option(range_display_options option) const - { - m_range_option = option; - } - - //! Change the delimiter strings - void delimiter_strings(const string_type& separator, - const string_type& start_delim, - const string_type& open_end_delim, - const string_type& closed_end_delim) - { - m_period_separator = separator; - m_period_start_delimeter = start_delim; - m_open_range_end_delimeter = open_end_delim; - m_closed_range_end_delimeter = closed_end_delim; - } - - //! Generic code to output a period -- no matter the period type. - /*! This generic code will output any period using a facet to - * to output the 'elements'. For example, in the case of a date_period - * the elements will be instances of a date which will be formatted - * according the to setup in the passed facet parameter. - * - * The steps for formatting a period are always the same: - * - put the start delimiter - * - put start element - * - put the separator - * - put either last or end element depending on range settings - * - put end delimeter depending on range settings - * - * Thus for a typical date period the result might look like this: - *@code - * - * [March 01, 2004/June 07, 2004] <-- closed range - * [March 01, 2004/June 08, 2004) <-- open range - * - *@endcode - */ - template - OutItrT put_period(OutItrT next, - std::ios_base& a_ios, - char_type a_fill, - const period_type& p, - const facet_type& facet) const { - put_period_start_delimeter(next); - next = facet.put(next, a_ios, a_fill, p.begin()); - put_period_separator(next); - if (m_range_option == AS_CLOSED_RANGE) { - facet.put(next, a_ios, a_fill, p.last()); - } - else { - facet.put(next, a_ios, a_fill, p.end()); - } - put_period_end_delimeter(next); - return next; - } - - - private: - range_display_options m_range_option; - string_type m_period_separator; - string_type m_period_start_delimeter; - string_type m_open_range_end_delimeter; - string_type m_closed_range_end_delimeter; - }; - - template - const typename period_formatter::char_type - period_formatter::default_period_separator[2] = {'/'}; - - template - const typename period_formatter::char_type - period_formatter::default_period_start_delimeter[2] = {'['}; - - template - const typename period_formatter::char_type - period_formatter::default_period_open_range_end_delimeter[2] = {')'}; - - template - const typename period_formatter::char_type - period_formatter::default_period_closed_range_end_delimeter[2] = {']'}; - - } } //namespace boost::date_time - -#endif diff --git a/boost/date_time/period_parser.hpp b/boost/date_time/period_parser.hpp deleted file mode 100644 index 7e4cdc7..0000000 --- a/boost/date_time/period_parser.hpp +++ /dev/null @@ -1,197 +0,0 @@ - -#ifndef DATETIME_PERIOD_PARSER_HPP___ -#define DATETIME_PERIOD_PARSER_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace boost { namespace date_time { - - - //! Not a facet, but a class used to specify and control period parsing - /*! Provides settings for the following: - * - period_separator -- default '/' - * - period_open_start_delimeter -- default '[' - * - period_open_range_end_delimeter -- default ')' - * - period_closed_range_end_delimeter -- default ']' - * - display_as_open_range, display_as_closed_range -- default closed_range - * - * For a typical date_period, the contents of the input stream would be - *@code - * [2004-Jan-04/2004-Feb-01] - *@endcode - * where the date format is controlled by the date facet - */ - template - class period_parser { - public: - typedef std::basic_string string_type; - typedef CharT char_type; - //typedef typename std::basic_string::const_iterator const_itr_type; - typedef std::istreambuf_iterator stream_itr_type; - typedef string_parse_tree parse_tree_type; - typedef typename parse_tree_type::parse_match_result_type match_results; - typedef std::vector > collection_type; - - static const char_type default_period_separator[2]; - static const char_type default_period_start_delimeter[2]; - static const char_type default_period_open_range_end_delimeter[2]; - static const char_type default_period_closed_range_end_delimeter[2]; - - enum period_range_option { AS_OPEN_RANGE, AS_CLOSED_RANGE }; - - //! Constructor that sets up period parser options - period_parser(period_range_option range_opt = AS_CLOSED_RANGE, - const char_type* const period_separator = default_period_separator, - const char_type* const period_start_delimeter = default_period_start_delimeter, - const char_type* const period_open_range_end_delimeter = default_period_open_range_end_delimeter, - const char_type* const period_closed_range_end_delimeter = default_period_closed_range_end_delimeter) - : m_range_option(range_opt) - { - delimiters.push_back(string_type(period_separator)); - delimiters.push_back(string_type(period_start_delimeter)); - delimiters.push_back(string_type(period_open_range_end_delimeter)); - delimiters.push_back(string_type(period_closed_range_end_delimeter)); - } - - period_range_option range_option() const - { - return m_range_option; - } - void range_option(period_range_option option) - { - m_range_option = option; - } - collection_type delimiter_strings() const - { - return delimiters; - } - void delimiter_strings(const string_type& separator, - const string_type& start_delim, - const string_type& open_end_delim, - const string_type& closed_end_delim) - { - delimiters.clear(); - delimiters.push_back(separator); - delimiters.push_back(start_delim); - delimiters.push_back(open_end_delim); - delimiters.push_back(closed_end_delim); - } - - //! Generic code to parse a period -- no matter the period type. - /*! This generic code will parse any period using a facet to - * to get the 'elements'. For example, in the case of a date_period - * the elements will be instances of a date which will be parsed - * according the to setup in the passed facet parameter. - * - * The steps for parsing a period are always the same: - * - consume the start delimiter - * - get start element - * - consume the separator - * - get either last or end element depending on range settings - * - consume the end delimeter depending on range settings - * - * Thus for a typical date period the contents of the input stream - * might look like this: - *@code - * - * [March 01, 2004/June 07, 2004] <-- closed range - * [March 01, 2004/June 08, 2004) <-- open range - * - *@endcode - */ - template - period_type get_period(stream_itr_type& sitr, - stream_itr_type& stream_end, - std::ios_base& a_ios, - const period_type& /* p */, - const duration_type& dur_unit, - const facet_type& facet) const - { - // skip leading whitespace - while(std::isspace(*sitr) && sitr != stream_end) { ++sitr; } - - typedef typename period_type::point_type point_type; - point_type p1(not_a_date_time), p2(not_a_date_time); - - - consume_delim(sitr, stream_end, delimiters[START]); // start delim - facet.get(sitr, stream_end, a_ios, p1); // first point - consume_delim(sitr, stream_end, delimiters[SEPARATOR]); // separator - facet.get(sitr, stream_end, a_ios, p2); // second point - - // period construction parameters are always open range [begin, end) - if (m_range_option == AS_CLOSED_RANGE) { - consume_delim(sitr, stream_end, delimiters[CLOSED_END]);// end delim - // add 1 duration unit to p2 to make range open - p2 += dur_unit; - } - else { - consume_delim(sitr, stream_end, delimiters[OPEN_END]); // end delim - } - - return period_type(p1, p2); - } - - private: - collection_type delimiters; - period_range_option m_range_option; - - enum delim_ids { SEPARATOR, START, OPEN_END, CLOSED_END }; - - //! throws ios_base::failure if delimiter and parsed data do not match - void consume_delim(stream_itr_type& sitr, - stream_itr_type& stream_end, - const string_type& delim) const - { - /* string_parse_tree will not parse a string of punctuation characters - * without knowing exactly how many characters to process - * Ex [2000. Will not parse out the '[' string without knowing - * to process only one character. By using length of the delimiter - * string we can safely iterate past it. */ - string_type s; - for(unsigned int i = 0; i < delim.length() && sitr != stream_end; ++i) { - s += *sitr; - ++sitr; - } - if(s != delim) { - boost::throw_exception(std::ios_base::failure("Parse failed. Expected '" - + convert_string_type(delim) + "' but found '" + convert_string_type(s) + "'")); - } - } - }; - - template - const typename period_parser::char_type - period_parser::default_period_separator[2] = {'/'}; - - template - const typename period_parser::char_type - period_parser::default_period_start_delimeter[2] = {'['}; - - template - const typename period_parser::char_type - period_parser::default_period_open_range_end_delimeter[2] = {')'}; - - template - const typename period_parser::char_type - period_parser::default_period_closed_range_end_delimeter[2] = {']'}; - - } } //namespace boost::date_time - -#endif // DATETIME_PERIOD_PARSER_HPP___ diff --git a/boost/date_time/posix_time/conversion.hpp b/boost/date_time/posix_time/conversion.hpp deleted file mode 100644 index d094544..0000000 --- a/boost/date_time/posix_time/conversion.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef POSIX_TIME_CONVERSION_HPP___ -#define POSIX_TIME_CONVERSION_HPP___ - -/* Copyright (c) 2002-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include // absolute_value -#include - -namespace boost { - -namespace posix_time { - - //! Function that converts a time_t into a ptime. - inline - ptime from_time_t(std::time_t t) - { - return ptime(gregorian::date(1970,1,1)) + seconds(t); - } - - //! Function that converts a ptime into a time_t - inline - std::time_t to_time_t(ptime pt) - { - return (pt - ptime(gregorian::date(1970,1,1))).total_seconds(); - } - - //! Convert a time to a tm structure truncating any fractional seconds - inline - std::tm to_tm(const boost::posix_time::ptime& t) { - std::tm timetm = boost::gregorian::to_tm(t.date()); - boost::posix_time::time_duration td = t.time_of_day(); - timetm.tm_hour = static_cast(td.hours()); - timetm.tm_min = static_cast(td.minutes()); - timetm.tm_sec = static_cast(td.seconds()); - timetm.tm_isdst = -1; // -1 used when dst info is unknown - return timetm; - } - //! Convert a time_duration to a tm structure truncating any fractional seconds and zeroing fields for date components - inline - std::tm to_tm(const boost::posix_time::time_duration& td) { - std::tm timetm; - std::memset(&timetm, 0, sizeof(timetm)); - timetm.tm_hour = static_cast(date_time::absolute_value(td.hours())); - timetm.tm_min = static_cast(date_time::absolute_value(td.minutes())); - timetm.tm_sec = static_cast(date_time::absolute_value(td.seconds())); - timetm.tm_isdst = -1; // -1 used when dst info is unknown - return timetm; - } - - //! Convert a tm struct to a ptime ignoring is_dst flag - inline - ptime ptime_from_tm(const std::tm& timetm) { - boost::gregorian::date d = boost::gregorian::date_from_tm(timetm); - return ptime(d, time_duration(timetm.tm_hour, timetm.tm_min, timetm.tm_sec)); - } - - -#if defined(BOOST_HAS_FTIME) - - //! Function to create a time object from an initialized FILETIME struct. - /*! Function to create a time object from an initialized FILETIME struct. - * A FILETIME struct holds 100-nanosecond units (0.0000001). When - * built with microsecond resolution the FILETIME's sub second value - * will be truncated. Nanosecond resolution has no truncation. - * - * \note FILETIME is part of the Win32 API, so it is not portable to non-windows - * platforms. - * - * \note The function is templated on the FILETIME type, so that - * it can be used with both native FILETIME and the ad-hoc - * boost::detail::winapi::FILETIME_ type. - */ - template< typename TimeT, typename FileTimeT > - inline - TimeT from_ftime(const FileTimeT& ft) - { - return boost::date_time::time_from_ftime(ft); - } - -#endif // BOOST_HAS_FTIME - -} } //namespace boost::posix_time - - - - -#endif - diff --git a/boost/date_time/posix_time/posix_time.hpp b/boost/date_time/posix_time/posix_time.hpp deleted file mode 100644 index aecf8a8..0000000 --- a/boost/date_time/posix_time/posix_time.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef POSIX_TIME_HPP___ -#define POSIX_TIME_HPP___ - -/* Copyright (c) 2002-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ -/*!@file posix_time.hpp Global header file to get all of posix time types - */ - -#include "boost/date_time/compiler_config.hpp" -#include "boost/date_time/posix_time/ptime.hpp" -#if defined(BOOST_DATE_TIME_OPTIONAL_GREGORIAN_TYPES) -#include "boost/date_time/posix_time/date_duration_operators.hpp" -#endif - -// output functions -#if defined(BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS) -#include "boost/date_time/posix_time/time_formatters_limited.hpp" -#else -#include "boost/date_time/posix_time/time_formatters.hpp" -#endif // BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS - -// streaming operators -#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) -#include "boost/date_time/posix_time/posix_time_legacy_io.hpp" -#else -#include "boost/date_time/posix_time/posix_time_io.hpp" -#endif // USE_DATE_TIME_PRE_1_33_FACET_IO - -#include "boost/date_time/posix_time/time_parsers.hpp" -#include "boost/date_time/posix_time/conversion.hpp" - - -#endif - diff --git a/boost/date_time/posix_time/posix_time_io.hpp b/boost/date_time/posix_time/posix_time_io.hpp deleted file mode 100644 index 6a72e32..0000000 --- a/boost/date_time/posix_time/posix_time_io.hpp +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef DATE_TIME_POSIX_TIME_IO_HPP__ -#define DATE_TIME_POSIX_TIME_IO_HPP__ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include // i/ostreambuf_iterator -#include -#include -#include -#include -#include -#include -#include // to_tm will be needed in the facets - -namespace boost { -namespace posix_time { - - - //! wptime_facet is depricated and will be phased out. use wtime_facet instead - //typedef boost::date_time::time_facet wptime_facet; - //! ptime_facet is depricated and will be phased out. use time_facet instead - //typedef boost::date_time::time_facet ptime_facet; - - //! wptime_input_facet is depricated and will be phased out. use wtime_input_facet instead - //typedef boost::date_time::time_input_facet wptime_input_facet; - //! ptime_input_facet is depricated and will be phased out. use time_input_facet instead - //typedef boost::date_time::time_input_facet ptime_input_facet; - - typedef boost::date_time::time_facet wtime_facet; - typedef boost::date_time::time_facet time_facet; - - typedef boost::date_time::time_input_facet wtime_input_facet; - typedef boost::date_time::time_input_facet time_input_facet; - - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const ptime& p) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::time_facet custom_ptime_facet; - std::ostreambuf_iterator oitr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); - else { - //instantiate a custom facet for dealing with times since the user - //has not put one in the stream so far. This is for efficiency - //since we would always need to reconstruct for every time period - //if the locale did not already exist. Of course this will be overridden - //if the user imbues as some later point. - custom_ptime_facet* f = new custom_ptime_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(oitr, os, os.fill(), p); - } - return os; - } - - //! input operator for ptime - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, ptime& pt) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::time_input_facet time_input_facet_local; - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, pt); - } - else { - time_input_facet_local* f = new time_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, pt); - } - } - catch(...) { - // mask tells us what exceptions are turned on - std::ios_base::iostate exception_mask = is.exceptions(); - // if the user wants exceptions on failbit, we'll rethrow our - // date_time exception & set the failbit - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} // ignore this one - throw; // rethrow original exception - } - else { - // if the user wants to fail quietly, we simply set the failbit - is.setstate(std::ios_base::failbit); - } - } - } - return is; - } - - - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, - const boost::posix_time::time_period& p) { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::time_facet custom_ptime_facet; - std::ostreambuf_iterator oitr(os); - if (std::has_facet(os.getloc())) { - std::use_facet(os.getloc()).put(oitr, os, os.fill(), p); - } - else { - //instantiate a custom facet for dealing with periods since the user - //has not put one in the stream so far. This is for efficiency - //since we would always need to reconstruct for every time period - //if the local did not already exist. Of course this will be overridden - //if the user imbues as some later point. - custom_ptime_facet* f = new custom_ptime_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(oitr, os, os.fill(), p); - } - return os; - } - - //! input operator for time_period - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, time_period& tp) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::time_input_facet time_input_facet_local; - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, tp); - } - else { - time_input_facet_local* f = new time_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, tp); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - } - } - return is; - } - - - //! ostream operator for posix_time::time_duration - // todo fix to use facet -- place holder for now... - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_duration& td) - { - boost::io::ios_flags_saver iflags(os); - typedef boost::date_time::time_facet custom_ptime_facet; - std::ostreambuf_iterator oitr(os); - if (std::has_facet(os.getloc())) - std::use_facet(os.getloc()).put(oitr, os, os.fill(), td); - else { - //instantiate a custom facet for dealing with times since the user - //has not put one in the stream so far. This is for efficiency - //since we would always need to reconstruct for every time period - //if the locale did not already exist. Of course this will be overridden - //if the user imbues as some later point. - custom_ptime_facet* f = new custom_ptime_facet(); - std::locale l = std::locale(os.getloc(), f); - os.imbue(l); - f->put(oitr, os, os.fill(), td); - } - return os; - } - - //! input operator for time_duration - template - inline - std::basic_istream& - operator>>(std::basic_istream& is, time_duration& td) - { - boost::io::ios_flags_saver iflags(is); - typename std::basic_istream::sentry strm_sentry(is, false); - if (strm_sentry) { - try { - typedef typename date_time::time_input_facet time_input_facet_local; - std::istreambuf_iterator sit(is), str_end; - if(std::has_facet(is.getloc())) { - std::use_facet(is.getloc()).get(sit, str_end, is, td); - } - else { - time_input_facet_local* f = new time_input_facet_local(); - std::locale l = std::locale(is.getloc(), f); - is.imbue(l); - f->get(sit, str_end, is, td); - } - } - catch(...) { - std::ios_base::iostate exception_mask = is.exceptions(); - if(std::ios_base::failbit & exception_mask) { - try { is.setstate(std::ios_base::failbit); } - catch(std::ios_base::failure&) {} - throw; // rethrow original exception - } - else { - is.setstate(std::ios_base::failbit); - } - } - } - return is; - } - -} } // namespaces -#endif // DATE_TIME_POSIX_TIME_IO_HPP__ diff --git a/boost/date_time/posix_time/posix_time_legacy_io.hpp b/boost/date_time/posix_time/posix_time_legacy_io.hpp deleted file mode 100644 index b31fb98..0000000 --- a/boost/date_time/posix_time/posix_time_legacy_io.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef POSIX_TIME_PRE133_OPERATORS_HPP___ -#define POSIX_TIME_PRE133_OPERATORS_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -/*! @file posix_time_pre133_operators.hpp - * These input and output operators are for use with the - * pre 1.33 version of the date_time libraries io facet code. - * The operators used in version 1.33 and later can be found - * in posix_time_io.hpp */ - -#include -#include -#include -#include "boost/date_time/compiler_config.hpp" -#include "boost/date_time/gregorian/gregorian.hpp" -#include "boost/date_time/posix_time/posix_time_duration.hpp" -#include "boost/date_time/posix_time/ptime.hpp" -#include "boost/date_time/posix_time/time_period.hpp" -#include "boost/date_time/time_parsing.hpp" - -namespace boost { -namespace posix_time { - - -//The following code is removed for configurations with poor std::locale support (eg: MSVC6, gcc 2.9x) -#ifndef BOOST_DATE_TIME_NO_LOCALE -#if defined(USE_DATE_TIME_PRE_1_33_FACET_IO) - //! ostream operator for posix_time::time_duration - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_duration& td) - { - typedef boost::date_time::ostream_time_duration_formatter duration_formatter; - duration_formatter::duration_put(td, os); - return os; - } - - //! ostream operator for posix_time::ptime - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const ptime& t) - { - typedef boost::date_time::ostream_time_formatter time_formatter; - time_formatter::time_put(t, os); - return os; - } - - //! ostream operator for posix_time::time_period - template - inline - std::basic_ostream& - operator<<(std::basic_ostream& os, const time_period& tp) - { - typedef boost::date_time::ostream_time_period_formatter period_formatter; - period_formatter::period_put(tp, os); - return os; - } -#endif // USE_DATE_TIME_PRE_1_33_FACET_IO -/******** input streaming ********/ - template - inline - std::basic_istream& operator>>(std::basic_istream& is, time_duration& td) - { - // need to create a std::string and parse it - std::basic_string inp_s; - std::stringstream out_ss; - is >> inp_s; - typename std::basic_string::iterator b = inp_s.begin(); - // need to use both iterators because there is no requirement - // for the data held by a std::basic_string<> be terminated with - // any marker (such as '\0'). - typename std::basic_string::iterator e = inp_s.end(); - while(b != e){ - out_ss << is.narrow(*b, 0); - ++b; - } - - td = date_time::parse_delimited_time_duration(out_ss.str()); - return is; - } - - template - inline - std::basic_istream& operator>>(std::basic_istream& is, ptime& pt) - { - gregorian::date d(not_a_date_time); - time_duration td(0,0,0); - is >> d >> td; - pt = ptime(d, td); - - return is; - } - - /** operator>> for time_period. time_period must be in - * "[date time_duration/date time_duration]" format. */ - template - inline - std::basic_istream& operator>>(std::basic_istream& is, time_period& tp) - { - gregorian::date d(not_a_date_time); - time_duration td(0,0,0); - ptime beg(d, td); - ptime end(beg); - std::basic_string s; - // get first date string and remove leading '[' - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(s.find('[')+1); - ss >> d; - } - // get first time_duration & second date string, remove the '/' - // and split into 2 strings - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(0, s.find('/')); - ss >> td; - } - beg = ptime(d, td); - { - std::basic_stringstream ss; - ss << s.substr(s.find('/')+1); - ss >> d; - } - // get last time_duration and remove the trailing ']' - is >> s; - { - std::basic_stringstream ss; - ss << s.substr(0, s.find(']')); - ss >> td; - } - end = ptime(d, td); - - tp = time_period(beg,end); - return is; - } - - -#endif //BOOST_DATE_TIME_NO_LOCALE - -} } // namespaces - -#endif // POSIX_TIME_PRE133_OPERATORS_HPP___ diff --git a/boost/date_time/posix_time/time_formatters.hpp b/boost/date_time/posix_time/time_formatters.hpp deleted file mode 100644 index e9122db..0000000 --- a/boost/date_time/posix_time/time_formatters.hpp +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef POSIXTIME_FORMATTERS_HPP___ -#define POSIXTIME_FORMATTERS_HPP___ - -/* Copyright (c) 2002-2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include // absolute_value -#include - -/* NOTE: The "to_*_string" code for older compilers, ones that define - * BOOST_DATE_TIME_INCLUDE_LIMITED_HEADERS, is located in - * formatters_limited.hpp - */ - -namespace boost { - -namespace posix_time { - - // template function called by wrapper functions: - // to_*_string(time_duration) & to_*_wstring(time_duration) - template - inline std::basic_string to_simple_string_type(time_duration td) { - std::basic_ostringstream ss; - if(td.is_special()) { - /* simply using 'ss << td.get_rep()' won't work on compilers - * that don't support locales. This way does. */ - // switch copied from date_names_put.hpp - switch(td.get_rep().as_special()) - { - case not_a_date_time: - //ss << "not-a-number"; - ss << "not-a-date-time"; - break; - case pos_infin: - ss << "+infinity"; - break; - case neg_infin: - ss << "-infinity"; - break; - default: - ss << ""; - } - } - else { - charT fill_char = '0'; - if(td.is_negative()) { - ss << '-'; - } - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.hours()) << ":"; - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.minutes()) << ":"; - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.seconds()); - //TODO the following is totally non-generic, yelling FIXME -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - boost::int64_t frac_sec = - date_time::absolute_value(td.fractional_seconds()); - // JDG [7/6/02 VC++ compatibility] - charT buff[32]; - _i64toa(frac_sec, buff, 10); -#else - time_duration::fractional_seconds_type frac_sec = - date_time::absolute_value(td.fractional_seconds()); -#endif - if (frac_sec != 0) { - ss << "." << std::setw(time_duration::num_fractional_digits()) - << std::setfill(fill_char) - - // JDG [7/6/02 VC++ compatibility] -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - << buff; -#else - << frac_sec; -#endif - } - }// else - return ss.str(); - } - //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline std::string to_simple_string(time_duration td) { - return to_simple_string_type(td); - } - - - // template function called by wrapper functions: - // to_*_string(time_duration) & to_*_wstring(time_duration) - template - inline std::basic_string to_iso_string_type(time_duration td) - { - std::basic_ostringstream ss; - if(td.is_special()) { - /* simply using 'ss << td.get_rep()' won't work on compilers - * that don't support locales. This way does. */ - // switch copied from date_names_put.hpp - switch(td.get_rep().as_special()) { - case not_a_date_time: - //ss << "not-a-number"; - ss << "not-a-date-time"; - break; - case pos_infin: - ss << "+infinity"; - break; - case neg_infin: - ss << "-infinity"; - break; - default: - ss << ""; - } - } - else { - charT fill_char = '0'; - if(td.is_negative()) { - ss << '-'; - } - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.hours()); - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.minutes()); - ss << std::setw(2) << std::setfill(fill_char) - << date_time::absolute_value(td.seconds()); - //TODO the following is totally non-generic, yelling FIXME -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - boost::int64_t frac_sec = - date_time::absolute_value(td.fractional_seconds()); - // JDG [7/6/02 VC++ compatibility] - charT buff[32]; - _i64toa(frac_sec, buff, 10); -#else - time_duration::fractional_seconds_type frac_sec = - date_time::absolute_value(td.fractional_seconds()); -#endif - if (frac_sec != 0) { - ss << "." << std::setw(time_duration::num_fractional_digits()) - << std::setfill(fill_char) - - // JDG [7/6/02 VC++ compatibility] -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - << buff; -#else - << frac_sec; -#endif - } - }// else - return ss.str(); - } - //! Time duration in ISO 8601 format -hhmmss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline std::string to_iso_string(time_duration td){ - return to_iso_string_type(td); - } - - //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff - /*!\ingroup time_format - */ - template - inline std::basic_string to_simple_string_type(ptime t) - { - // can't use this w/gcc295, no to_simple_string_type<>(td) available - std::basic_string ts = gregorian::to_simple_string_type(t.date());// + " "; - if(!t.time_of_day().is_special()) { - charT space = ' '; - return ts + space + to_simple_string_type(t.time_of_day()); - } - else { - return ts; - } - } - inline std::string to_simple_string(ptime t){ - return to_simple_string_type(t); - } - - // function called by wrapper functions to_*_string(time_period) - // & to_*_wstring(time_period) - template - inline std::basic_string to_simple_string_type(time_period tp) - { - charT beg = '[', mid = '/', end = ']'; - std::basic_string d1(to_simple_string_type(tp.begin())); - std::basic_string d2(to_simple_string_type(tp.last())); - return std::basic_string(beg + d1 + mid + d2 + end); - } - //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] - /*!\ingroup time_format - */ - inline std::string to_simple_string(time_period tp){ - return to_simple_string_type(tp); - } - - // function called by wrapper functions to_*_string(time_period) - // & to_*_wstring(time_period) - template - inline std::basic_string to_iso_string_type(ptime t) - { - std::basic_string ts = gregorian::to_iso_string_type(t.date());// + "T"; - if(!t.time_of_day().is_special()) { - charT sep = 'T'; - return ts + sep + to_iso_string_type(t.time_of_day()); - } - else { - return ts; - } - } - //! Convert ISO 8601 short form YYYYMMDDTHHMMSS where T is the date-time separator - /*!\ingroup time_format - */ - inline std::string to_iso_string(ptime t){ - return to_iso_string_type(t); - } - - - // function called by wrapper functions to_*_string(time_period) - // & to_*_wstring(time_period) - template - inline std::basic_string to_iso_extended_string_type(ptime t) - { - std::basic_string ts = gregorian::to_iso_extended_string_type(t.date());// + "T"; - if(!t.time_of_day().is_special()) { - charT sep = 'T'; - return ts + sep + to_simple_string_type(t.time_of_day()); - } - else { - return ts; - } - } - //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator - /*!\ingroup time_format - */ - inline std::string to_iso_extended_string(ptime t){ - return to_iso_extended_string_type(t); - } - -#if !defined(BOOST_NO_STD_WSTRING) - //! Time duration to wstring -hh::mm::ss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline std::wstring to_simple_wstring(time_duration td) { - return to_simple_string_type(td); - } - //! Time duration in ISO 8601 format -hhmmss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline std::wstring to_iso_wstring(time_duration td){ - return to_iso_string_type(td); - } - inline std::wstring to_simple_wstring(ptime t){ - return to_simple_string_type(t); - } - //! Convert to wstring of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] - /*!\ingroup time_format - */ - inline std::wstring to_simple_wstring(time_period tp){ - return to_simple_string_type(tp); - } - //! Convert ISO 8601 short form YYYYMMDDTHHMMSS where T is the date-time separator - /*!\ingroup time_format - */ - inline std::wstring to_iso_wstring(ptime t){ - return to_iso_string_type(t); - } - //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator - /*!\ingroup time_format - */ - inline std::wstring to_iso_extended_wstring(ptime t){ - return to_iso_extended_string_type(t); - } - -#endif // BOOST_NO_STD_WSTRING - - -} } //namespace posix_time - - -#endif - diff --git a/boost/date_time/posix_time/time_formatters_limited.hpp b/boost/date_time/posix_time/time_formatters_limited.hpp deleted file mode 100644 index a5e5f71..0000000 --- a/boost/date_time/posix_time/time_formatters_limited.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef POSIXTIME_FORMATTERS_LIMITED_HPP___ -#define POSIXTIME_FORMATTERS_LIMITED_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include -#include -#include -#include // absolute_value - -namespace boost { - -namespace posix_time { - - //! Time duration to string -hh::mm::ss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline std::string to_simple_string(time_duration td) { - std::ostringstream ss; - if(td.is_special()) { - /* simply using 'ss << td.get_rep()' won't work on compilers - * that don't support locales. This way does. */ - // switch copied from date_names_put.hpp - switch(td.get_rep().as_special()) - { - case not_a_date_time: - //ss << "not-a-number"; - ss << "not-a-date-time"; - break; - case pos_infin: - ss << "+infinity"; - break; - case neg_infin: - ss << "-infinity"; - break; - default: - ss << ""; - } - } - else { - if(td.is_negative()) { - ss << '-'; - } - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.hours()) << ":"; - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.minutes()) << ":"; - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.seconds()); - //TODO the following is totally non-generic, yelling FIXME -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - boost::int64_t frac_sec = - date_time::absolute_value(td.fractional_seconds()); - // JDG [7/6/02 VC++ compatibility] - char buff[32]; - _i64toa(frac_sec, buff, 10); -#else - time_duration::fractional_seconds_type frac_sec = - date_time::absolute_value(td.fractional_seconds()); -#endif - if (frac_sec != 0) { - ss << "." << std::setw(time_duration::num_fractional_digits()) - << std::setfill('0') - - // JDG [7/6/02 VC++ compatibility] -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - << buff; -#else - << frac_sec; -#endif - } - }// else - return ss.str(); - } - - //! Time duration in ISO 8601 format -hhmmss.fffffff. Example: 10:09:03.0123456 - /*!\ingroup time_format - */ - inline - std::string - to_iso_string(time_duration td) - { - std::ostringstream ss; - if(td.is_special()) { - /* simply using 'ss << td.get_rep()' won't work on compilers - * that don't support locales. This way does. */ - // switch copied from date_names_put.hpp - switch(td.get_rep().as_special()) { - case not_a_date_time: - //ss << "not-a-number"; - ss << "not-a-date-time"; - break; - case pos_infin: - ss << "+infinity"; - break; - case neg_infin: - ss << "-infinity"; - break; - default: - ss << ""; - } - } - else { - if(td.is_negative()) { - ss << '-'; - } - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.hours()); - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.minutes()); - ss << std::setw(2) << std::setfill('0') - << date_time::absolute_value(td.seconds()); - //TODO the following is totally non-generic, yelling FIXME -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - boost::int64_t frac_sec = - date_time::absolute_value(td.fractional_seconds()); - // JDG [7/6/02 VC++ compatibility] - char buff[32]; - _i64toa(frac_sec, buff, 10); -#else - time_duration::fractional_seconds_type frac_sec = - date_time::absolute_value(td.fractional_seconds()); -#endif - if (frac_sec != 0) { - ss << "." << std::setw(time_duration::num_fractional_digits()) - << std::setfill('0') - - // JDG [7/6/02 VC++ compatibility] -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - << buff; -#else - << frac_sec; -#endif - } - }// else - return ss.str(); - } - - //! Time to simple format CCYY-mmm-dd hh:mm:ss.fffffff - /*!\ingroup time_format - */ - inline - std::string - to_simple_string(ptime t) - { - std::string ts = gregorian::to_simple_string(t.date());// + " "; - if(!t.time_of_day().is_special()) { - return ts + " " + to_simple_string(t.time_of_day()); - } - else { - return ts; - } - } - - //! Convert to string of form [YYYY-mmm-DD HH:MM::SS.ffffff/YYYY-mmm-DD HH:MM::SS.fffffff] - /*!\ingroup time_format - */ - inline - std::string - to_simple_string(time_period tp) - { - std::string d1(to_simple_string(tp.begin())); - std::string d2(to_simple_string(tp.last())); - return std::string("[" + d1 + "/" + d2 +"]"); - } - - //! Convert ISO 8601 short form YYYYMMDDTHHMMSS where T is the date-time separator - /*!\ingroup time_format - */ - inline - std::string to_iso_string(ptime t) - { - std::string ts = gregorian::to_iso_string(t.date());// + "T"; - if(!t.time_of_day().is_special()) { - return ts + "T" + to_iso_string(t.time_of_day()); - } - else { - return ts; - } - } - - //! Convert to form YYYY-MM-DDTHH:MM:SS where T is the date-time separator - /*!\ingroup time_format - */ - inline - std::string - to_iso_extended_string(ptime t) - { - std::string ts = gregorian::to_iso_extended_string(t.date());// + "T"; - if(!t.time_of_day().is_special()) { - return ts + "T" + to_simple_string(t.time_of_day()); - } - else { - return ts; - } - } - - -} } //namespace posix_time - - -#endif - diff --git a/boost/date_time/posix_time/time_parsers.hpp b/boost/date_time/posix_time/time_parsers.hpp deleted file mode 100644 index 738de6f..0000000 --- a/boost/date_time/posix_time/time_parsers.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef POSIXTIME_PARSERS_HPP___ -#define POSIXTIME_PARSERS_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland - * $Date$ - */ - -#include "boost/date_time/gregorian/gregorian.hpp" -#include "boost/date_time/time_parsing.hpp" -#include "boost/date_time/posix_time/posix_time_types.hpp" - - -namespace boost { - -namespace posix_time { - - //! Creates a time_duration object from a delimited string - /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". - * A negative duration will be created if the first character in - * string is a '-', all other '-' will be treated as delimiters. - * Accepted delimiters are "-:,.". */ - inline time_duration duration_from_string(const std::string& s) { - return date_time::parse_delimited_time_duration(s); - } - - inline ptime time_from_string(const std::string& s) { - return date_time::parse_delimited_time(s, ' '); - } - - inline ptime from_iso_string(const std::string& s) { - return date_time::parse_iso_time(s, 'T'); - } - - inline ptime from_iso_extended_string(const std::string& s) { - if (s.size() == 10) { //assume we just have a date which is 10 chars - gregorian::date d = gregorian::from_simple_string(s); - return ptime( d ); - } - return date_time::parse_delimited_time(s, 'T'); - } - - - -} } //namespace posix_time - - -#endif - diff --git a/boost/date_time/special_values_formatter.hpp b/boost/date_time/special_values_formatter.hpp deleted file mode 100644 index 0eb3cae..0000000 --- a/boost/date_time/special_values_formatter.hpp +++ /dev/null @@ -1,97 +0,0 @@ - -#ifndef DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ -#define DATETIME_SPECIAL_VALUE_FORMATTER_HPP___ - -/* Copyright (c) 2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland - * $Date$ - */ - -#include -#include -#include -#include "boost/date_time/special_defs.hpp" - -namespace boost { namespace date_time { - - - //! Class that provides generic formmatting ostream formatting for special values - /*! This class provides for the formmating of special values to an output stream. - * In particular, it produces strings for the values of negative and positive - * infinity as well as not_a_date_time. - * - * While not a facet, this class is used by the date and time facets for formatting - * special value types. - * - */ - template > > - class special_values_formatter - { - public: - typedef std::basic_string string_type; - typedef CharT char_type; - typedef std::vector collection_type; - static const char_type default_special_value_names[3][17]; - - //! Construct special values formatter using default strings. - /*! Default strings are not-a-date-time -infinity +infinity - */ - special_values_formatter() - { - std::copy(&default_special_value_names[0], - &default_special_value_names[3], - std::back_inserter(m_special_value_names)); - } - - //! Construct special values formatter from array of strings - /*! This constructor will take pair of iterators from an array of strings - * that represent the special values and copy them for use in formatting - * special values. - *@code - * const char* const special_value_names[]={"nadt","-inf","+inf" }; - * - * special_value_formatter svf(&special_value_names[0], &special_value_names[3]); - *@endcode - */ - special_values_formatter(const char_type* const* begin, const char_type* const* end) - { - std::copy(begin, end, std::back_inserter(m_special_value_names)); - } - special_values_formatter(typename collection_type::iterator beg, typename collection_type::iterator end) - { - std::copy(beg, end, std::back_inserter(m_special_value_names)); - } - - OutItrT put_special(OutItrT next, - const boost::date_time::special_values& value) const - { - - unsigned int index = value; - if (index < m_special_value_names.size()) { - std::copy(m_special_value_names[index].begin(), - m_special_value_names[index].end(), - next); - } - return next; - } - protected: - collection_type m_special_value_names; - }; - - //! Storage for the strings used to indicate special values - /* using c_strings to initialize these worked fine in testing, however, - * a project that compiled its objects separately, then linked in a separate - * step wound up with redefinition errors for the values in this array. - * Initializing individual characters eliminated this problem */ - template - const typename special_values_formatter::char_type special_values_formatter::default_special_value_names[3][17] = { - {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}, - {'-','i','n','f','i','n','i','t','y'}, - {'+','i','n','f','i','n','i','t','y'} }; - - } } //namespace boost::date_time - -#endif diff --git a/boost/date_time/special_values_parser.hpp b/boost/date_time/special_values_parser.hpp deleted file mode 100644 index 7b493c8..0000000 --- a/boost/date_time/special_values_parser.hpp +++ /dev/null @@ -1,163 +0,0 @@ - -#ifndef DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ -#define DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ - -/* Copyright (c) 2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date: - */ - - -#include "boost/date_time/string_parse_tree.hpp" -#include "boost/date_time/special_defs.hpp" -#include -#include - -namespace boost { namespace date_time { - - //! Class for special_value parsing - /*! - * TODO: add doc-comments for which elements can be changed - * Parses input stream for strings representing special_values. - * Special values parsed are: - * - not_a_date_time - * - neg_infin - * - pod_infin - * - min_date_time - * - max_date_time - */ - template - class special_values_parser - { - public: - typedef std::basic_string string_type; - typedef std::basic_stringstream stringstream_type; - typedef std::istreambuf_iterator stream_itr_type; - typedef typename date_type::duration_type duration_type; - typedef string_parse_tree parse_tree_type; - typedef typename parse_tree_type::parse_match_result_type match_results; - typedef std::vector > collection_type; - - typedef charT char_type; - static const char_type nadt_string[16]; - static const char_type neg_inf_string[10]; - static const char_type pos_inf_string[10]; - static const char_type min_date_time_string[18]; - static const char_type max_date_time_string[18]; - - //! Creates a special_values_parser with the default set of "sv_strings" - special_values_parser() - { - sv_strings(string_type(nadt_string), - string_type(neg_inf_string), - string_type(pos_inf_string), - string_type(min_date_time_string), - string_type(max_date_time_string)); - } - - //! Creates a special_values_parser using a user defined set of element strings - special_values_parser(const string_type& nadt_str, - const string_type& neg_inf_str, - const string_type& pos_inf_str, - const string_type& min_dt_str, - const string_type& max_dt_str) - { - sv_strings(nadt_str, neg_inf_str, pos_inf_str, min_dt_str, max_dt_str); - } - - special_values_parser(typename collection_type::iterator beg, typename collection_type::iterator end) - { - collection_type phrases; - std::copy(beg, end, std::back_inserter(phrases)); - m_sv_strings = parse_tree_type(phrases, static_cast(not_a_date_time)); - } - - //! Replace special value strings - void sv_strings(const string_type& nadt_str, - const string_type& neg_inf_str, - const string_type& pos_inf_str, - const string_type& min_dt_str, - const string_type& max_dt_str) - { - collection_type phrases; - phrases.push_back(nadt_str); - phrases.push_back(neg_inf_str); - phrases.push_back(pos_inf_str); - phrases.push_back(min_dt_str); - phrases.push_back(max_dt_str); - m_sv_strings = parse_tree_type(phrases, static_cast(not_a_date_time)); - } - - //! The parser is expensive to create, and not thread-safe so it cannot be static - //! therefore given a string, determine if it is likely to be a special value. - //! A negative response is a definite no, whereas a positive is only likely and - //! match() should be called and return value checked. - //! \param[in] str the string to check - //! \returns false if it is definitely not a special value - static bool should_call_match(const string_type& str) - { - if (!str.empty()) { - switch (str[0]) { - // See string definitions at the end of this class.. - case '+': - case '-': - case 'n': - case 'm': - return true; - - default: - break; - } - } - - return false; - } - - //! Given an input iterator, attempt to match it to a known special value - //! \param[in] sitr the start iterator - //! \param[in] str_end the end iterator - //! \param[out] mr the match result: - //! mr.current_match is set to the corresponding special_value or -1 - //! \returns whether something matched - bool match(stream_itr_type& sitr, - stream_itr_type& str_end, - match_results& mr) const - { - unsigned int level = 0; - m_sv_strings.match(sitr, str_end, mr, level); - return (mr.current_match != match_results::PARSE_ERROR); - } - - private: - parse_tree_type m_sv_strings; - - }; - - template - const typename special_values_parser::char_type - special_values_parser::nadt_string[16] = - {'n','o','t','-','a','-','d','a','t','e','-','t','i','m','e'}; - template - const typename special_values_parser::char_type - special_values_parser::neg_inf_string[10] = - {'-','i','n','f','i','n','i','t','y'}; - template - const typename special_values_parser::char_type - special_values_parser::pos_inf_string[10] = - {'+','i','n','f','i','n','i','t','y'}; - template - const typename special_values_parser::char_type - special_values_parser::min_date_time_string[18] = - {'m','i','n','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; - template - const typename special_values_parser::char_type - special_values_parser::max_date_time_string[18] = - {'m','a','x','i','m','u','m','-','d','a','t','e','-','t','i','m','e'}; - -} } //namespace - -#endif // DATE_TIME_SPECIAL_VALUES_PARSER_HPP__ - diff --git a/boost/date_time/string_convert.hpp b/boost/date_time/string_convert.hpp deleted file mode 100644 index 30be356..0000000 --- a/boost/date_time/string_convert.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _STRING_CONVERT_HPP___ -#define _STRING_CONVERT_HPP___ - -/* Copyright (c) 2005 CrystalClear Software, Inc. - * Subject to the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/date_time/compiler_config.hpp" -#include - -namespace boost { -namespace date_time { - - //! Converts a string from one value_type to another - /*! Converts a wstring to a string (or a string to wstring). If both template parameters - * are of same type, a copy of the input string is returned. */ - template - inline - std::basic_string convert_string_type(const std::basic_string& inp_str) - { - typedef std::basic_string output_type; - output_type result; - result.insert(result.begin(), inp_str.begin(), inp_str.end()); - return result; - } - -}} // namespace boost::date_time - -#endif // _STRING_CONVERT_HPP___ diff --git a/boost/date_time/string_parse_tree.hpp b/boost/date_time/string_parse_tree.hpp deleted file mode 100644 index ecac863..0000000 --- a/boost/date_time/string_parse_tree.hpp +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ -#define BOOST_DATE_TIME_STRING_PARSE_TREE___HPP__ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace date_time { - - -template -struct parse_match_result -{ - parse_match_result() : - match_depth(0), - current_match(PARSE_ERROR) - {} - typedef std::basic_string string_type; - string_type remaining() const - { - if (match_depth == cache.size()) { - return string_type(); - } - if (current_match == PARSE_ERROR) { - return cache; - } - //some of the cache was used return the rest - return string_type(cache, match_depth); - } - charT last_char() const - { - return cache[cache.size()-1]; - } - //! Returns true if more characters were parsed than was necessary - /*! Should be used in conjunction with last_char() - * to get the remaining character. - */ - bool has_remaining() const - { - return (cache.size() > match_depth); - } - - // cache will hold characters that have been read from the stream - string_type cache; - unsigned short match_depth; - short current_match; - enum PARSE_STATE { PARSE_ERROR = -1 }; -}; - - //for debug -- really only char streams... -template -std::basic_ostream& -operator<<(std::basic_ostream& os, parse_match_result& mr) -{ - os << "cm: " << mr.current_match - << " C: '" << mr.cache - << "' md: " << mr.match_depth - << " R: " << mr.remaining(); - return os; -} - - - -//! Recursive data structure to allow efficient parsing of various strings -/*! This class provides a quick lookup by building what amounts to a - * tree data structure. It also features a match function which can - * can handle nasty input interators by caching values as it recurses - * the tree so that it can backtrack as needed. - */ -template -struct string_parse_tree -{ -#if BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT(0x581) ) - typedef std::multimap > ptree_coll; -#else - typedef std::multimap ptree_coll; -#endif - typedef typename ptree_coll::value_type value_type; - typedef typename ptree_coll::iterator iterator; - typedef typename ptree_coll::const_iterator const_iterator; - typedef std::basic_string string_type; - typedef std::vector > collection_type; - typedef parse_match_result parse_match_result_type; - - /*! Parameter "starting_point" designates where the numbering begins. - * A starting_point of zero will start the numbering at zero - * (Sun=0, Mon=1, ...) were a starting_point of one starts the - * numbering at one (Jan=1, Feb=2, ...). The default is zero, - * negative vaules are not allowed */ - string_parse_tree(collection_type names, unsigned int starting_point=0) : - m_value(parse_match_result_type::PARSE_ERROR) - { - // iterate thru all the elements and build the tree - unsigned short index = 0; - while (index != names.size() ) { - string_type s = boost::algorithm::to_lower_copy(names[index]); - insert(s, static_cast(index + starting_point)); - index++; - } - //set the last tree node = index+1 indicating a value - index++; - } - - - string_parse_tree(short value = parse_match_result_type::PARSE_ERROR) : - m_value(value) - {} - ptree_coll m_next_chars; - short m_value; - - void insert(const string_type& s, unsigned short value) - { - unsigned int i = 0; - iterator ti; - while(i < s.size()) { - if (i==0) { - if (i == (s.size()-1)) { - ti = m_next_chars.insert(value_type(s[i], - string_parse_tree(value))); - } - else { - ti = m_next_chars.insert(value_type(s[i], - string_parse_tree())); - } - } - else { - if (i == (s.size()-1)) { - ti = ti->second.m_next_chars.insert(value_type(s[i], - string_parse_tree(value))); - } - - else { - ti = ti->second.m_next_chars.insert(value_type(s[i], - string_parse_tree())); - } - - } - i++; - } - } - - - //! Recursive function that finds a matching string in the tree. - /*! Must check match_results::has_remaining() after match() is - * called. This is required so the user can determine if - * stream iterator is already pointing to the expected - * character or not (match() might advance sitr to next char in stream). - * - * A parse_match_result that has been returned from a failed match - * attempt can be sent in to the match function of a different - * string_parse_tree to attempt a match there. Use the iterators - * for the partially consumed stream, the parse_match_result object, - * and '0' for the level parameter. */ - short - match(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end, - parse_match_result_type& result, - unsigned int& level) const - { - - level++; - charT c; - // if we conditionally advance sitr, we won't have - // to consume the next character past the input - bool adv_itr = true; - if (level > result.cache.size()) { - if (sitr == stream_end) return 0; //bail - input exhausted - c = static_cast(std::tolower(*sitr)); - //result.cache += c; - //sitr++; - } - else { - // if we're looking for characters from the cache, - // we don't want to increment sitr - adv_itr = false; - c = static_cast(std::tolower(result.cache[level-1])); - } - const_iterator litr = m_next_chars.lower_bound(c); - const_iterator uitr = m_next_chars.upper_bound(c); - while (litr != uitr) { // equal if not found - if(adv_itr) { - sitr++; - result.cache += c; - } - if (litr->second.m_value != -1) { // -1 is default value - if (result.match_depth < level) { - result.current_match = litr->second.m_value; - result.match_depth = static_cast(level); - } - litr->second.match(sitr, stream_end, - result, level); - level--; - } - else { - litr->second.match(sitr, stream_end, - result, level); - level--; - } - - if(level <= result.cache.size()) { - adv_itr = false; - } - - litr++; - } - return result.current_match; - - } - - /*! Must check match_results::has_remaining() after match() is - * called. This is required so the user can determine if - * stream iterator is already pointing to the expected - * character or not (match() might advance sitr to next char in stream). - */ - parse_match_result_type - match(std::istreambuf_iterator& sitr, - std::istreambuf_iterator& stream_end) const - { - // lookup to_lower of char in tree. - unsigned int level = 0; - // string_type cache; - parse_match_result_type result; - match(sitr, stream_end, result, level); - return result; - } - - void printme(std::ostream& os, int& level) - { - level++; - iterator itr = m_next_chars.begin(); - iterator end = m_next_chars.end(); - // os << "starting level: " << level << std::endl; - while (itr != end) { - os << "level: " << level - << " node: " << itr->first - << " value: " << itr->second.m_value - << std::endl; - itr->second.printme(os, level); - itr++; - } - level--; - } - - void print(std::ostream& os) - { - int level = 0; - printme(os, level); - } - - void printmatch(std::ostream& os, charT c) - { - iterator litr = m_next_chars.lower_bound(c); - iterator uitr = m_next_chars.upper_bound(c); - os << "matches for: " << c << std::endl; - while (litr != uitr) { - os << " node: " << litr->first - << " value: " << litr->second.m_value - << std::endl; - litr++; - } - } - -}; - - -} } //namespace -#endif diff --git a/boost/date_time/strings_from_facet.hpp b/boost/date_time/strings_from_facet.hpp deleted file mode 100644 index cecd32f..0000000 --- a/boost/date_time/strings_from_facet.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef DATE_TIME_STRINGS_FROM_FACET__HPP___ -#define DATE_TIME_STRINGS_FROM_FACET__HPP___ - -/* Copyright (c) 2004 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland - * $Date$ - */ - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace date_time { - -//! This function gathers up all the month strings from a std::locale -/*! Using the time_put facet, this function creates a collection of - * all the month strings from a locale. This is handy when building - * custom date parsers or formatters that need to be localized. - * - *@param charT The type of char to use when gathering typically char - * or wchar_t. - *@param locale The locale to use when gathering the strings - *@param short_strings True(default) to gather short strings, - * false for long strings. - *@return A vector of strings containing the strings in order. eg: - * Jan, Feb, Mar, etc. - */ -template -std::vector > -gather_month_strings(const std::locale& locale, bool short_strings=true) -{ - typedef std::basic_string string_type; - typedef std::vector collection_type; - typedef std::ostreambuf_iterator ostream_iter_type; - typedef std::basic_ostringstream stringstream_type; - typedef std::time_put time_put_facet_type; - charT short_fmt[3] = { '%', 'b' }; - charT long_fmt[3] = { '%', 'B' }; - collection_type months; - string_type outfmt(short_fmt); - if (!short_strings) { - outfmt = long_fmt; - } - { - //grab the needed strings by using the locale to - //output each month - const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size(); - tm tm_value; - std::memset(&tm_value, 0, sizeof(tm_value)); - for (int m=0; m < 12; m++) { - tm_value.tm_mon = m; - stringstream_type ss; - ostream_iter_type oitr(ss); - std::use_facet(locale).put(oitr, ss, ss.fill(), - &tm_value, - p_outfmt, - p_outfmt_end); - months.push_back(ss.str()); - } - } - return months; -} - -//! This function gathers up all the weekday strings from a std::locale -/*! Using the time_put facet, this function creates a collection of - * all the weekday strings from a locale starting with the string for - * 'Sunday'. This is handy when building custom date parsers or - * formatters that need to be localized. - * - *@param charT The type of char to use when gathering typically char - * or wchar_t. - *@param locale The locale to use when gathering the strings - *@param short_strings True(default) to gather short strings, - * false for long strings. - *@return A vector of strings containing the weekdays in order. eg: - * Sun, Mon, Tue, Wed, Thu, Fri, Sat - */ -template -std::vector > -gather_weekday_strings(const std::locale& locale, bool short_strings=true) -{ - typedef std::basic_string string_type; - typedef std::vector collection_type; - typedef std::ostreambuf_iterator ostream_iter_type; - typedef std::basic_ostringstream stringstream_type; - typedef std::time_put time_put_facet_type; - charT short_fmt[3] = { '%', 'a' }; - charT long_fmt[3] = { '%', 'A' }; - - collection_type weekdays; - - - string_type outfmt(short_fmt); - if (!short_strings) { - outfmt = long_fmt; - } - { - //grab the needed strings by using the locale to - //output each month / weekday - const charT* p_outfmt = outfmt.c_str(), *p_outfmt_end = p_outfmt + outfmt.size(); - tm tm_value; - std::memset(&tm_value, 0, sizeof(tm_value)); - for (int i=0; i < 7; i++) { - tm_value.tm_wday = i; - stringstream_type ss; - ostream_iter_type oitr(ss); - std::use_facet(locale).put(oitr, ss, ss.fill(), - &tm_value, - p_outfmt, - p_outfmt_end); - - weekdays.push_back(ss.str()); - } - } - return weekdays; -} - -} } //namespace - - -#endif diff --git a/boost/date_time/time_facet.hpp b/boost/date_time/time_facet.hpp deleted file mode 100644 index 98c133a..0000000 --- a/boost/date_time/time_facet.hpp +++ /dev/null @@ -1,1370 +0,0 @@ - -#ifndef _DATE_TIME_FACET__HPP__ -#define _DATE_TIME_FACET__HPP__ - -/* Copyright (c) 2004-2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Martin Andrian, Jeff Garland, Bart Garst - * $Date$ - */ - -#include -#include -#include -#include // i/ostreambuf_iterator -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // absolute_value - -namespace boost { -namespace date_time { - - template - struct time_formats { - public: - typedef CharT char_type; - static const char_type fractional_seconds_format[3]; // f - static const char_type fractional_seconds_or_none_format[3]; // F - static const char_type seconds_with_fractional_seconds_format[3]; // s - static const char_type seconds_format[3]; // S - static const char_type hours_format[3]; // H - static const char_type unrestricted_hours_format[3]; // O - static const char_type full_24_hour_time_format[3]; // T - static const char_type full_24_hour_time_expanded_format[9]; // HH:MM:SS - static const char_type short_24_hour_time_format[3]; // R - static const char_type short_24_hour_time_expanded_format[6]; // HH:MM - static const char_type standard_format[9]; // x X - static const char_type zone_abbrev_format[3]; // z - static const char_type zone_name_format[3]; // Z - static const char_type zone_iso_format[3]; // q - static const char_type zone_iso_extended_format[3]; // Q - static const char_type posix_zone_string_format[4]; // ZP - static const char_type duration_sign_negative_only[3]; // - - static const char_type duration_sign_always[3]; // + - static const char_type duration_seperator[2]; - static const char_type negative_sign[2]; //- - static const char_type positive_sign[2]; //+ - static const char_type iso_time_format_specifier[18]; - static const char_type iso_time_format_extended_specifier[22]; - //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] - static const char_type default_time_format[23]; - // default_time_input_format uses a posix_time_zone_string instead of a time zone abbrev - static const char_type default_time_input_format[24]; - //default time_duration format is HH:MM:SS[.fff...] - static const char_type default_time_duration_format[11]; - }; - - template - const typename time_formats::char_type - time_formats::fractional_seconds_format[3] = {'%','f'}; - - template - const typename time_formats::char_type - time_formats::fractional_seconds_or_none_format[3] = {'%','F'}; - - template - const typename time_formats::char_type - time_formats::seconds_with_fractional_seconds_format[3] = {'%','s'}; - - template - const typename time_formats::char_type - time_formats::seconds_format[3] = {'%','S'}; - - template - const typename time_formats::char_type - time_formats::hours_format[3] = {'%','H'}; - - template - const typename time_formats::char_type - time_formats::unrestricted_hours_format[3] = {'%','O'}; - - template - const typename time_formats::char_type - time_formats::full_24_hour_time_format[3] = {'%','T'}; - - template - const typename time_formats::char_type - time_formats::full_24_hour_time_expanded_format[9] = - {'%','H',':','%','M',':','%','S'}; - - template - const typename time_formats::char_type - time_formats::short_24_hour_time_format[3] = {'%','R'}; - - template - const typename time_formats::char_type - time_formats::short_24_hour_time_expanded_format[6] = - {'%','H',':','%','M'}; - - template - const typename time_formats::char_type - //time_formats::standard_format[5] = {'%','c',' ','%','z'}; - time_formats::standard_format[9] = {'%','x',' ','%','X',' ','%','z'}; - - template - const typename time_formats::char_type - time_formats::zone_abbrev_format[3] = {'%','z'}; - - template - const typename time_formats::char_type - time_formats::zone_name_format[3] = {'%','Z'}; - - template - const typename time_formats::char_type - time_formats::zone_iso_format[3] = {'%','q'}; - - template - const typename time_formats::char_type - time_formats::zone_iso_extended_format[3] ={'%','Q'}; - - template - const typename time_formats::char_type - time_formats::posix_zone_string_format[4] ={'%','Z','P'}; - - template - const typename time_formats::char_type - time_formats::duration_seperator[2] = {':'}; - - template - const typename time_formats::char_type - time_formats::negative_sign[2] = {'-'}; - - template - const typename time_formats::char_type - time_formats::positive_sign[2] = {'+'}; - - template - const typename time_formats::char_type - time_formats::duration_sign_negative_only[3] ={'%','-'}; - - template - const typename time_formats::char_type - time_formats::duration_sign_always[3] ={'%','+'}; - - template - const typename time_formats::char_type - time_formats::iso_time_format_specifier[18] = - {'%', 'Y', '%', 'm', '%', 'd', 'T', - '%', 'H', '%', 'M', '%', 'S', '%', 'F', '%','q' }; - - template - const typename time_formats::char_type - time_formats::iso_time_format_extended_specifier[22] = - {'%', 'Y', '-', '%', 'm', '-', '%', 'd', ' ', - '%', 'H', ':', '%', 'M', ':', '%', 'S', '%', 'F','%','Q'}; - - template - const typename time_formats::char_type - time_formats::default_time_format[23] = - {'%','Y','-','%','b','-','%','d',' ', - '%','H',':','%','M',':','%','S','%','F',' ','%','z'}; - - template - const typename time_formats::char_type - time_formats::default_time_input_format[24] = - {'%','Y','-','%','b','-','%','d',' ', - '%','H',':','%','M',':','%','S','%','F',' ','%','Z','P'}; - - template - const typename time_formats::char_type - time_formats::default_time_duration_format[11] = - {'%','O',':','%','M',':','%','S','%','F'}; - - - - /*! Facet used for format-based output of time types - * This class provides for the use of format strings to output times. In addition - * to the flags for formatting date elements, the following are the allowed format flags: - * - %x %X => default format - enables addition of more flags to default (ie. "%x %X %z") - * - %f => fractional seconds ".123456" - * - %F => fractional seconds or none: like frac sec but empty if frac sec == 0 - * - %s => seconds w/ fractional sec "02.123" (this is the same as "%S%f) - * - %S => seconds "02" - * - %z => abbreviated time zone "EDT" - * - %Z => full time zone name "Eastern Daylight Time" - */ - template > > - class BOOST_SYMBOL_VISIBLE time_facet : - public boost::date_time::date_facet { - typedef time_formats< CharT > formats_type; - public: - typedef typename time_type::date_type date_type; - typedef typename time_type::time_duration_type time_duration_type; - typedef boost::date_time::period period_type; - typedef boost::date_time::date_facet base_type; - typedef typename base_type::string_type string_type; - typedef typename base_type::char_type char_type; - typedef typename base_type::period_formatter_type period_formatter_type; - typedef typename base_type::special_values_formatter_type special_values_formatter_type; - typedef typename base_type::date_gen_formatter_type date_gen_formatter_type; - static const char_type* fractional_seconds_format; // %f - static const char_type* fractional_seconds_or_none_format; // %F - static const char_type* seconds_with_fractional_seconds_format; // %s - static const char_type* seconds_format; // %S - static const char_type* hours_format; // %H - static const char_type* unrestricted_hours_format; // %O - static const char_type* standard_format; // %x X - static const char_type* zone_abbrev_format; // %z - static const char_type* zone_name_format; // %Z - static const char_type* zone_iso_format; // %q - static const char_type* zone_iso_extended_format; // %Q - static const char_type* posix_zone_string_format; // %ZP - static const char_type* duration_seperator; - static const char_type* duration_sign_always; // %+ - static const char_type* duration_sign_negative_only; // %- - static const char_type* negative_sign; //- - static const char_type* positive_sign; //+ - static const char_type* iso_time_format_specifier; - static const char_type* iso_time_format_extended_specifier; - - //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] - static const char_type* default_time_format; - //default time_duration format is HH:MM:SS[.fff...] - static const char_type* default_time_duration_format; - static std::locale::id id; - -#if defined (__SUNPRO_CC) && defined (_RWSTD_VER) - std::locale::id& __get_id (void) const { return id; } -#endif - - //! sets default formats for ptime, local_date_time, and time_duration - explicit time_facet(::size_t ref_arg = 0) - : base_type(default_time_format, period_formatter_type(), special_values_formatter_type(), date_gen_formatter_type(), ref_arg), - m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) - {} - - //! Construct the facet with an explicitly specified format - explicit time_facet(const char_type* format_arg, - period_formatter_type period_formatter_arg = period_formatter_type(), - const special_values_formatter_type& special_value_formatter = special_values_formatter_type(), - date_gen_formatter_type dg_formatter = date_gen_formatter_type(), - ::size_t ref_arg = 0) - : base_type(format_arg, - period_formatter_arg, - special_value_formatter, - dg_formatter, - ref_arg), - m_time_duration_format(string_type(duration_sign_negative_only) + default_time_duration_format) - {} - - //! Changes format for time_duration - void time_duration_format(const char_type* const format) - { - m_time_duration_format = format; - } - - void set_iso_format() BOOST_OVERRIDE - { - this->m_format = iso_time_format_specifier; - } - void set_iso_extended_format() BOOST_OVERRIDE - { - this->m_format = iso_time_format_extended_specifier; - } - - OutItrT put(OutItrT next_arg, - std::ios_base& ios_arg, - char_type fill_arg, - const time_type& time_arg) const - { - if (time_arg.is_special()) { - return this->do_put_special(next_arg, ios_arg, fill_arg, - time_arg.date().as_special()); - } - string_type local_format(this->m_format); - - // %T and %R have to be replaced here since they are not standard - boost::algorithm::replace_all(local_format, - boost::as_literal(formats_type::full_24_hour_time_format), - boost::as_literal(formats_type::full_24_hour_time_expanded_format)); - boost::algorithm::replace_all(local_format, - boost::as_literal(formats_type::short_24_hour_time_format), - boost::as_literal(formats_type::short_24_hour_time_expanded_format)); - - string_type frac_str; - if (local_format.find(seconds_with_fractional_seconds_format) != string_type::npos) { - // replace %s with %S.nnn - frac_str = - fractional_seconds_as_string(time_arg.time_of_day(), false); - char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); - - string_type replace_string(seconds_format); - replace_string += sep; - replace_string += frac_str; - boost::algorithm::replace_all(local_format, - seconds_with_fractional_seconds_format, - replace_string); - } - /* NOTE: replacing posix_zone_string_format must be done BEFORE - * zone_name_format: "%ZP" & "%Z", if Z is checked first it will - * incorrectly replace a zone_name where a posix_string should go */ - if (local_format.find(posix_zone_string_format) != string_type::npos) { - if(time_arg.zone_abbrev().empty()) { - // if zone_abbrev() returns an empty string, we want to - // erase posix_zone_string_format from format - boost::algorithm::erase_all(local_format, posix_zone_string_format); - } - else{ - boost::algorithm::replace_all(local_format, - posix_zone_string_format, - time_arg.zone_as_posix_string()); - } - } - if (local_format.find(zone_name_format) != string_type::npos) { - if(time_arg.zone_name().empty()) { - /* TODO: this'll probably create problems if a user places - * the zone_*_format flag in the format with a ptime. This - * code removes the flag from the default formats */ - - // if zone_name() returns an empty string, we want to - // erase zone_name_format & one preceeding space - std::basic_ostringstream ss; - ss << ' ' << zone_name_format; - boost::algorithm::erase_all(local_format, ss.str()); - } - else{ - boost::algorithm::replace_all(local_format, - zone_name_format, - time_arg.zone_name()); - } - } - if (local_format.find(zone_abbrev_format) != string_type::npos) { - if(time_arg.zone_abbrev(false).empty()) { - /* TODO: this'll probably create problems if a user places - * the zone_*_format flag in the format with a ptime. This - * code removes the flag from the default formats */ - - // if zone_abbrev() returns an empty string, we want to - // erase zone_abbrev_format & one preceeding space - std::basic_ostringstream ss; - ss << ' ' << zone_abbrev_format; - boost::algorithm::erase_all(local_format, ss.str()); - } - else{ - boost::algorithm::replace_all(local_format, - zone_abbrev_format, - time_arg.zone_abbrev(false)); - } - } - if (local_format.find(zone_iso_extended_format) != string_type::npos) { - if(time_arg.zone_name(true).empty()) { - /* TODO: this'll probably create problems if a user places - * the zone_*_format flag in the format with a ptime. This - * code removes the flag from the default formats */ - - // if zone_name() returns an empty string, we want to - // erase zone_iso_extended_format from format - boost::algorithm::erase_all(local_format, zone_iso_extended_format); - } - else{ - boost::algorithm::replace_all(local_format, - zone_iso_extended_format, - time_arg.zone_name(true)); - } - } - - if (local_format.find(zone_iso_format) != string_type::npos) { - if(time_arg.zone_abbrev(true).empty()) { - /* TODO: this'll probably create problems if a user places - * the zone_*_format flag in the format with a ptime. This - * code removes the flag from the default formats */ - - // if zone_abbrev() returns an empty string, we want to - // erase zone_iso_format from format - boost::algorithm::erase_all(local_format, zone_iso_format); - } - else{ - boost::algorithm::replace_all(local_format, - zone_iso_format, - time_arg.zone_abbrev(true)); - } - } - if (local_format.find(fractional_seconds_format) != string_type::npos) { - // replace %f with nnnnnnn - if (frac_str.empty()) { - frac_str = fractional_seconds_as_string(time_arg.time_of_day(), false); - } - boost::algorithm::replace_all(local_format, - fractional_seconds_format, - frac_str); - } - - if (local_format.find(fractional_seconds_or_none_format) != string_type::npos) { - // replace %F with nnnnnnn or nothing if fs == 0 - frac_str = - fractional_seconds_as_string(time_arg.time_of_day(), true); - if (!frac_str.empty()) { - char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); - string_type replace_string; - replace_string += sep; - replace_string += frac_str; - boost::algorithm::replace_all(local_format, - fractional_seconds_or_none_format, - replace_string); - } - else { - boost::algorithm::erase_all(local_format, - fractional_seconds_or_none_format); - } - } - - return this->do_put_tm(next_arg, ios_arg, fill_arg, - to_tm(time_arg), local_format); - } - - //! put function for time_duration - OutItrT put(OutItrT next_arg, - std::ios_base& ios_arg, - char_type fill_arg, - const time_duration_type& time_dur_arg) const - { - if (time_dur_arg.is_special()) { - return this->do_put_special(next_arg, ios_arg, fill_arg, - time_dur_arg.get_rep().as_special()); - } - - string_type format(m_time_duration_format); - if (time_dur_arg.is_negative()) { - // replace %- with minus sign. Should we use the numpunct facet? - boost::algorithm::replace_all(format, - duration_sign_negative_only, - negative_sign); - // remove all the %+ in the string with '-' - boost::algorithm::replace_all(format, - duration_sign_always, - negative_sign); - } - else { //duration is positive - // remove all the %- combos from the string - boost::algorithm::erase_all(format, duration_sign_negative_only); - // remove all the %+ in the string with '+' - boost::algorithm::replace_all(format, - duration_sign_always, - positive_sign); - } - - // %T and %R have to be replaced here since they are not standard - boost::algorithm::replace_all(format, - boost::as_literal(formats_type::full_24_hour_time_format), - boost::as_literal(formats_type::full_24_hour_time_expanded_format)); - boost::algorithm::replace_all(format, - boost::as_literal(formats_type::short_24_hour_time_format), - boost::as_literal(formats_type::short_24_hour_time_expanded_format)); - - /* - * It is possible for a time duration to span more then 24 hours. - * Standard time_put::put is obliged to behave the same as strftime - * (See ISO 14882-2003 22.2.5.3.1 par. 1) and strftime's behavior is - * unspecified for the case when tm_hour field is outside 0-23 range - * (See ISO 9899-1999 7.23.3.5 par. 3). So we must output %H and %O - * here ourself. - */ - string_type hours_str; - if (format.find(unrestricted_hours_format) != string_type::npos) { - hours_str = hours_as_string(time_dur_arg); - boost::algorithm::replace_all(format, unrestricted_hours_format, hours_str); - } - // We still have to process restricted hours format specifier. In order to - // support parseability of durations in ISO 8601 format (%H%M%S), we'll have to - // restrict the stringified hours length to 2 characters. - if (format.find(hours_format) != string_type::npos) { - if (hours_str.empty()) - hours_str = hours_as_string(time_dur_arg); - BOOST_ASSERT(hours_str.length() <= 2); - boost::algorithm::replace_all(format, hours_format, hours_str); - } - - string_type frac_str; - if (format.find(seconds_with_fractional_seconds_format) != string_type::npos) { - // replace %s with %S.nnn - frac_str = - fractional_seconds_as_string(time_dur_arg, false); - char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); - - string_type replace_string(seconds_format); - replace_string += sep; - replace_string += frac_str; - boost::algorithm::replace_all(format, - seconds_with_fractional_seconds_format, - replace_string); - } - if (format.find(fractional_seconds_format) != string_type::npos) { - // replace %f with nnnnnnn - if (!frac_str.size()) { - frac_str = fractional_seconds_as_string(time_dur_arg, false); - } - boost::algorithm::replace_all(format, - fractional_seconds_format, - frac_str); - } - - if (format.find(fractional_seconds_or_none_format) != string_type::npos) { - // replace %F with nnnnnnn or nothing if fs == 0 - frac_str = - fractional_seconds_as_string(time_dur_arg, true); - if (frac_str.size()) { - char_type sep = std::use_facet >(ios_arg.getloc()).decimal_point(); - string_type replace_string; - replace_string += sep; - replace_string += frac_str; - boost::algorithm::replace_all(format, - fractional_seconds_or_none_format, - replace_string); - } - else { - boost::algorithm::erase_all(format, - fractional_seconds_or_none_format); - } - } - - return this->do_put_tm(next_arg, ios_arg, fill_arg, - to_tm(time_dur_arg), format); - } - - OutItrT put(OutItrT next, std::ios_base& ios_arg, - char_type fill, const period_type& p) const - { - return this->m_period_formatter.put_period(next, ios_arg, fill,p,*this); - } - - - protected: - - static - string_type - fractional_seconds_as_string(const time_duration_type& time_arg, - bool null_when_zero) - { - typename time_duration_type::fractional_seconds_type frac_sec = - time_arg.fractional_seconds(); - - if (null_when_zero && (frac_sec == 0)) { - return string_type(); - } - - //make sure there is no sign - return integral_as_string( - date_time::absolute_value(frac_sec), - time_duration_type::num_fractional_digits()); - } - - static - string_type - hours_as_string(const time_duration_type& time_arg, int width = 2) - { - return integral_as_string(date_time::absolute_value(time_arg.hours()), width); - } - - template< typename IntT > - static - string_type - integral_as_string(IntT val, int width = 2) - { - std::basic_ostringstream ss; - ss.imbue(std::locale::classic()); // don't want any formatting - ss << std::setw(width) - << std::setfill(static_cast('0')); -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - // JDG [7/6/02 VC++ compatibility] - char_type buff[34]; - ss << _i64toa(static_cast(val), buff, 10); -#else - ss << val; -#endif - return ss.str(); - } - - private: - string_type m_time_duration_format; - - }; - - template - std::locale::id time_facet::id; - - template - const typename time_facet::char_type* - time_facet::fractional_seconds_format = time_formats::fractional_seconds_format; - - template - const typename time_facet::char_type* - time_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; - - template - const typename time_facet::char_type* - time_facet::seconds_with_fractional_seconds_format = - time_formats::seconds_with_fractional_seconds_format; - - - template - const typename time_facet::char_type* - time_facet::zone_name_format = time_formats::zone_name_format; - - template - const typename time_facet::char_type* - time_facet::zone_abbrev_format = time_formats::zone_abbrev_format; - - template - const typename time_facet::char_type* - time_facet::zone_iso_extended_format =time_formats::zone_iso_extended_format; - - template - const typename time_facet::char_type* - time_facet::posix_zone_string_format =time_formats::posix_zone_string_format; - - template - const typename time_facet::char_type* - time_facet::zone_iso_format = time_formats::zone_iso_format; - - template - const typename time_facet::char_type* - time_facet::seconds_format = time_formats::seconds_format; - - template - const typename time_facet::char_type* - time_facet::hours_format = time_formats::hours_format; - - template - const typename time_facet::char_type* - time_facet::unrestricted_hours_format = time_formats::unrestricted_hours_format; - - template - const typename time_facet::char_type* - time_facet::standard_format = time_formats::standard_format; - - template - const typename time_facet::char_type* - time_facet::duration_seperator = time_formats::duration_seperator; - - template - const typename time_facet::char_type* - time_facet::negative_sign = time_formats::negative_sign; - - template - const typename time_facet::char_type* - time_facet::positive_sign = time_formats::positive_sign; - - template - const typename time_facet::char_type* - time_facet::duration_sign_negative_only = time_formats::duration_sign_negative_only; - - template - const typename time_facet::char_type* - time_facet::duration_sign_always = time_formats::duration_sign_always; - - template - const typename time_facet::char_type* - time_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; - - template - const typename time_facet::char_type* - time_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; - - template - const typename time_facet::char_type* - time_facet::default_time_format = - time_formats::default_time_format; - - template - const typename time_facet::char_type* - time_facet::default_time_duration_format = - time_formats::default_time_duration_format; - - - //! Facet for format-based input. - /*! - */ - template > > - class BOOST_SYMBOL_VISIBLE time_input_facet : - public boost::date_time::date_input_facet { - public: - typedef typename time_type::date_type date_type; - typedef typename time_type::time_duration_type time_duration_type; - typedef typename time_duration_type::fractional_seconds_type fracional_seconds_type; - typedef boost::date_time::period period_type; - typedef boost::date_time::date_input_facet base_type; - typedef typename base_type::duration_type date_duration_type; - typedef typename base_type::year_type year_type; - typedef typename base_type::month_type month_type; - typedef typename base_type::day_type day_type; - typedef typename base_type::string_type string_type; - typedef typename string_type::const_iterator const_itr; - typedef typename base_type::char_type char_type; - typedef typename base_type::format_date_parser_type format_date_parser_type; - typedef typename base_type::period_parser_type period_parser_type; - typedef typename base_type::special_values_parser_type special_values_parser_type; - typedef typename base_type::date_gen_parser_type date_gen_parser_type; - typedef typename base_type::special_values_parser_type::match_results match_results; - - static const char_type* fractional_seconds_format; // f - static const char_type* fractional_seconds_or_none_format; // F - static const char_type* seconds_with_fractional_seconds_format; // s - static const char_type* seconds_format; // S - static const char_type* standard_format; // x X - static const char_type* zone_abbrev_format; // z - static const char_type* zone_name_format; // Z - static const char_type* zone_iso_format; // q - static const char_type* zone_iso_extended_format; // Q - static const char_type* duration_seperator; - static const char_type* iso_time_format_specifier; - static const char_type* iso_time_format_extended_specifier; - static const char_type* default_time_input_format; - static const char_type* default_time_duration_format; - static std::locale::id id; - - //! Constructor that takes a format string for a ptime - explicit time_input_facet(const string_type& format, ::size_t ref_arg = 0) - : base_type(format, ref_arg), - m_time_duration_format(default_time_duration_format) - { } - - explicit time_input_facet(const string_type& format, - const format_date_parser_type& date_parser, - const special_values_parser_type& sv_parser, - const period_parser_type& per_parser, - const date_gen_parser_type& date_gen_parser, - ::size_t ref_arg = 0) - : base_type(format, - date_parser, - sv_parser, - per_parser, - date_gen_parser, - ref_arg), - m_time_duration_format(default_time_duration_format) - {} - - //! sets default formats for ptime, local_date_time, and time_duration - explicit time_input_facet(::size_t ref_arg = 0) - : base_type(default_time_input_format, ref_arg), - m_time_duration_format(default_time_duration_format) - { } - - //! Set the format for time_duration - void time_duration_format(const char_type* const format) { - m_time_duration_format = format; - } - virtual void set_iso_format() - { - this->m_format = iso_time_format_specifier; - } - virtual void set_iso_extended_format() - { - this->m_format = iso_time_format_extended_specifier; - } - - InItrT get(InItrT& sitr, - InItrT& stream_end, - std::ios_base& ios_arg, - period_type& p) const - { - p = this->m_period_parser.get_period(sitr, - stream_end, - ios_arg, - p, - time_duration_type::unit(), - *this); - return sitr; - } - - //default ptime format is YYYY-Mon-DD HH:MM:SS[.fff...][ zzz] - //default time_duration format is %H:%M:%S%F HH:MM:SS[.fff...] - - InItrT get(InItrT& sitr, - InItrT& stream_end, - std::ios_base& ios_arg, - time_duration_type& td) const - { - // skip leading whitespace - while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } - - bool use_current_char = false; - - // num_get will consume the +/-, we may need a copy if special_value - char_type c = '\0'; - if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { - c = *sitr; - } - - typedef typename time_duration_type::hour_type hour_type; - typedef typename time_duration_type::min_type min_type; - typedef typename time_duration_type::sec_type sec_type; - - hour_type hour = 0; - min_type min = 0; - sec_type sec = 0; - typename time_duration_type::fractional_seconds_type frac(0); - - typedef std::num_get num_get; - if(!std::has_facet(ios_arg.getloc())) { - num_get* ng = new num_get(); - std::locale loc = std::locale(ios_arg.getloc(), ng); - ios_arg.imbue(loc); - } - - const_itr itr(m_time_duration_format.begin()); - while (itr != m_time_duration_format.end() && (sitr != stream_end)) { - if (*itr == '%') { - if (++itr == m_time_duration_format.end()) break; - if (*itr != '%') { - switch(*itr) { - case 'O': - { - // A period may span more than 24 hours. In that case the format - // string should be composed with the unrestricted hours specifier. - hour = var_string_to_int(sitr, stream_end, - std::numeric_limits::digits10 + 1); - if(hour == -1){ - return check_special_value(sitr, stream_end, td, c); - } - break; - } - case 'H': - { - match_results mr; - hour = fixed_string_to_int(sitr, stream_end, mr, 2); - if(hour == -1){ - return check_special_value(sitr, stream_end, td, c); - } - break; - } - case 'M': - { - match_results mr; - min = fixed_string_to_int(sitr, stream_end, mr, 2); - if(min == -1){ - return check_special_value(sitr, stream_end, td, c); - } - break; - } - case 's': - case 'S': - { - match_results mr; - sec = fixed_string_to_int(sitr, stream_end, mr, 2); - if(sec == -1){ - return check_special_value(sitr, stream_end, td, c); - } - if (*itr == 'S') - break; - // %s is the same as %S%f so we drop through into %f - } - /* Falls through. */ - case 'f': - { - // check for decimal, check special_values if missing - if(*sitr == '.') { - ++sitr; - parse_frac_type(sitr, stream_end, frac); - // sitr will point to next expected char after this parsing - // is complete so no need to advance it - use_current_char = true; - } - else { - return check_special_value(sitr, stream_end, td, c); - } - break; - } - case 'F': - { - // check for decimal, skip if missing - if(*sitr == '.') { - ++sitr; - parse_frac_type(sitr, stream_end, frac); - // sitr will point to next expected char after this parsing - // is complete so no need to advance it - use_current_char = true; - } - else { - // nothing was parsed so we don't want to advance sitr - use_current_char = true; - } - break; - } - default: - {} // ignore what we don't understand? - }// switch - } - else { // itr == '%', second consecutive - ++sitr; - } - - ++itr; //advance past format specifier - } - else { //skip past chars in format and in buffer - ++itr; - // set use_current_char when sitr is already - // pointing at the next character to process - if (use_current_char) { - use_current_char = false; - } - else { - ++sitr; - } - } - } - - td = time_duration_type(hour, min, sec, frac); - return sitr; - } - - - //! Parses a time object from the input stream - InItrT get(InItrT& sitr, - InItrT& stream_end, - std::ios_base& ios_arg, - time_type& t) const - { - string_type tz_str; - return get(sitr, stream_end, ios_arg, t, tz_str, false); - } - //! Expects a time_zone in the input stream - InItrT get_local_time(InItrT& sitr, - InItrT& stream_end, - std::ios_base& ios_arg, - time_type& t, - string_type& tz_str) const - { - return get(sitr, stream_end, ios_arg, t, tz_str, true); - } - - protected: - - InItrT get(InItrT& sitr, - InItrT& stream_end, - std::ios_base& ios_arg, - time_type& t, - string_type& tz_str, - bool time_is_local) const - { - // skip leading whitespace - while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } - - bool use_current_char = false; - bool use_current_format_char = false; // used with two character flags - - // num_get will consume the +/-, we may need a copy if special_value - char_type c = '\0'; - if((sitr != stream_end) && (*sitr == '-' || *sitr == '+')) { - c = *sitr; - } - - typedef typename time_duration_type::hour_type hour_type; - typedef typename time_duration_type::min_type min_type; - typedef typename time_duration_type::sec_type sec_type; - - // time elements - hour_type hour = 0; - min_type min = 0; - sec_type sec = 0; - typename time_duration_type::fractional_seconds_type frac(0); - // date elements - short day_of_year(0); - /* Initialized the following to their minimum values. These intermediate - * objects are used so we get specific exceptions when part of the input - * is unparsable. - * Ex: "205-Jan-15" will throw a bad_year, "2005-Jsn-15"- bad_month, etc.*/ - year_type t_year(1400); - month_type t_month(1); - day_type t_day(1); - - typedef std::num_get num_get; - if(!std::has_facet(ios_arg.getloc())) { - num_get* ng = new num_get(); - std::locale loc = std::locale(ios_arg.getloc(), ng); - ios_arg.imbue(loc); - } - - const_itr itr(this->m_format.begin()); - while (itr != this->m_format.end() && (sitr != stream_end)) { - if (*itr == '%') { - if (++itr == this->m_format.end()) break; - if (*itr != '%') { - // the cases are grouped by date & time flags - not alphabetical order - switch(*itr) { - // date flags - case 'Y': - case 'y': - { - char_type cs[3] = { '%', *itr }; - string_type s(cs); - match_results mr; - try { - t_year = this->m_parser.parse_year(sitr, stream_end, s, mr); - } - catch(std::out_of_range&) { // base class for bad_year exception - if(this->m_sv_parser.match(sitr, stream_end, mr)) { - t = time_type(static_cast(mr.current_match)); - return sitr; - } - else { - throw; // rethrow bad_year - } - } - break; - } - case 'B': - case 'b': - case 'm': - { - char_type cs[3] = { '%', *itr }; - string_type s(cs); - match_results mr; - try { - t_month = this->m_parser.parse_month(sitr, stream_end, s, mr); - } - catch(std::out_of_range&) { // base class for bad_month exception - if(this->m_sv_parser.match(sitr, stream_end, mr)) { - t = time_type(static_cast(mr.current_match)); - return sitr; - } - else { - throw; // rethrow bad_month - } - } - // did m_parser already advance sitr to next char? - if(mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'a': - case 'A': - case 'w': - { - // weekday is not used in construction but we need to get it out of the stream - char_type cs[3] = { '%', *itr }; - string_type s(cs); - match_results mr; - typename date_type::day_of_week_type wd(0); - try { - wd = this->m_parser.parse_weekday(sitr, stream_end, s, mr); - } - catch(std::out_of_range&) { // base class for bad_weekday exception - if(this->m_sv_parser.match(sitr, stream_end, mr)) { - t = time_type(static_cast(mr.current_match)); - return sitr; - } - else { - throw; // rethrow bad_weekday - } - } - // did m_parser already advance sitr to next char? - if(mr.has_remaining()) { - use_current_char = true; - } - break; - } - case 'j': - { - // code that gets julian day (from format_date_parser) - match_results mr; - day_of_year = fixed_string_to_int(sitr, stream_end, mr, 3); - if(day_of_year == -1) { - if(this->m_sv_parser.match(sitr, stream_end, mr)) { - t = time_type(static_cast(mr.current_match)); - return sitr; - } - } - // these next two lines are so we get an exception with bad input - typedef typename time_type::date_type::day_of_year_type day_of_year_type; - day_of_year_type t_day_of_year(day_of_year); - break; - } - case 'd': - case 'e': - { - try { - t_day = (*itr == 'd') ? - this->m_parser.parse_day_of_month(sitr, stream_end) : - this->m_parser.parse_var_day_of_month(sitr, stream_end); - } - catch(std::out_of_range&) { // base class for exception bad_day_of_month - match_results mr; - if(this->m_sv_parser.match(sitr, stream_end, mr)) { - t = time_type(static_cast(mr.current_match)); - return sitr; - } - else { - throw; // rethrow bad_day_of_month - } - } - break; - } - // time flags - case 'H': - { - match_results mr; - hour = fixed_string_to_int(sitr, stream_end, mr, 2); - if(hour == -1){ - return check_special_value(sitr, stream_end, t, c); - } - break; - } - case 'M': - { - match_results mr; - min = fixed_string_to_int(sitr, stream_end, mr, 2); - if(min == -1){ - return check_special_value(sitr, stream_end, t, c); - } - break; - } - case 's': - case 'S': - { - match_results mr; - sec = fixed_string_to_int(sitr, stream_end, mr, 2); - if(sec == -1){ - return check_special_value(sitr, stream_end, t, c); - } - if (*itr == 'S' || sitr == stream_end) - break; - // %s is the same as %S%f so we drop through into %f if we are - // not at the end of the stream - } - /* Falls through. */ - case 'f': - { - // check for decimal, check SV if missing - if(*sitr == '.') { - ++sitr; - parse_frac_type(sitr, stream_end, frac); - // sitr will point to next expected char after this parsing - // is complete so no need to advance it - use_current_char = true; - } - else { - return check_special_value(sitr, stream_end, t, c); - } - break; - } - case 'F': - { - // check for decimal, skip if missing - if(*sitr == '.') { - ++sitr; - parse_frac_type(sitr, stream_end, frac); - // sitr will point to next expected char after this parsing - // is complete so no need to advance it - use_current_char = true; - } - else { - // nothing was parsed so we don't want to advance sitr - use_current_char = true; - } - break; - } - // time_zone flags - //case 'q': - //case 'Q': - //case 'z': - case 'Z': - { - if(time_is_local) { // skip if 't' is a ptime - ++itr; - if(*itr == 'P') { - // skip leading whitespace - while((sitr != stream_end) && std::isspace(*sitr)) { ++sitr; } - // parse zone - while((sitr != stream_end) && (!std::isspace(*sitr))) { - tz_str += *sitr; - ++sitr; - } - } - else { - use_current_format_char = true; - } - - } - else { - // nothing was parsed so we don't want to advance sitr - use_current_char = true; - } - - break; - } - default: - {} // ignore what we don't understand? - }// switch - } - else { // itr == '%', second consecutive - ++sitr; - } - - if(use_current_format_char) { - use_current_format_char = false; - } - else { - ++itr; //advance past format specifier - } - - } - else { //skip past chars in format and in buffer - ++itr; - // set use_current_char when sitr is already - // pointing at the next character to process - if (use_current_char) { - use_current_char = false; - } - else { - ++sitr; - } - } - } - - date_type d(not_a_date_time); - if (day_of_year > 0) { - d = date_type(static_cast(t_year),1,1) + date_duration_type(day_of_year-1); - } - else { - d = date_type(t_year, t_month, t_day); - } - - time_duration_type td(hour, min, sec, frac); - t = time_type(d, td); - return sitr; - } - - //! Helper function to check for special_value - /*! First character may have been consumed during original parse - * attempt. Parameter 'c' should be a copy of that character. - * Throws ios_base::failure if parse fails. */ - template - inline - InItrT check_special_value(InItrT& sitr,InItrT& stream_end, temporal_type& tt, char_type c='\0') const - { - match_results mr; - if((c == '-' || c == '+') && (*sitr != c)) { // was the first character consumed? - mr.cache += c; - } - (void)this->m_sv_parser.match(sitr, stream_end, mr); - if(mr.current_match == match_results::PARSE_ERROR) { - std::string tmp = convert_string_type(mr.cache); - boost::throw_exception(std::ios_base::failure("Parse failed. No match found for '" + tmp + "'")); - BOOST_DATE_TIME_UNREACHABLE_EXPRESSION(return sitr); // should never reach - } - tt = temporal_type(static_cast(mr.current_match)); - return sitr; - } - - //! Helper function for parsing a fractional second type from the stream - void parse_frac_type(InItrT& sitr, - InItrT& stream_end, - fracional_seconds_type& frac) const - { - string_type cache; - while((sitr != stream_end) && std::isdigit(*sitr)) { - cache += *sitr; - ++sitr; - } - if(cache.size() > 0) { - unsigned short precision = time_duration_type::num_fractional_digits(); - // input may be only the first few decimal places - if(cache.size() < precision) { - frac = lexical_cast(cache); - frac = decimal_adjust(frac, static_cast(precision - cache.size())); - } - else { - // if input has too many decimal places, drop excess digits - frac = lexical_cast(cache.substr(0, precision)); - } - } - } - - private: - string_type m_time_duration_format; - - //! Helper function to adjust trailing zeros when parsing fractional digits - template - inline - int_type decimal_adjust(int_type val, const unsigned short places) const - { - unsigned long factor = 1; - for(int i = 0; i < places; ++i){ - factor *= 10; // shift decimal to the right - } - return val * factor; - } - - }; - -template - std::locale::id time_input_facet::id; - -template - const typename time_input_facet::char_type* - time_input_facet::fractional_seconds_format = time_formats::fractional_seconds_format; - - template - const typename time_input_facet::char_type* - time_input_facet::fractional_seconds_or_none_format = time_formats::fractional_seconds_or_none_format; - - template - const typename time_input_facet::char_type* - time_input_facet::seconds_with_fractional_seconds_format = time_formats::seconds_with_fractional_seconds_format; - - template - const typename time_input_facet::char_type* - time_input_facet::seconds_format = time_formats::seconds_format; - - template - const typename time_input_facet::char_type* - time_input_facet::standard_format = time_formats::standard_format; - - template - const typename time_input_facet::char_type* - time_input_facet::zone_abbrev_format = time_formats::zone_abbrev_format; - - template - const typename time_input_facet::char_type* - time_input_facet::zone_name_format = time_formats::zone_name_format; - - template - const typename time_input_facet::char_type* - time_input_facet::zone_iso_format = time_formats::zone_iso_format; - - template - const typename time_input_facet::char_type* - time_input_facet::zone_iso_extended_format = time_formats::zone_iso_extended_format; - - template - const typename time_input_facet::char_type* - time_input_facet::duration_seperator = time_formats::duration_seperator; - - template - const typename time_input_facet::char_type* - time_input_facet::iso_time_format_specifier = time_formats::iso_time_format_specifier; - - template - const typename time_input_facet::char_type* - time_input_facet::iso_time_format_extended_specifier = time_formats::iso_time_format_extended_specifier; - - template - const typename time_input_facet::char_type* - time_input_facet::default_time_input_format = time_formats::default_time_input_format; - - template - const typename time_input_facet::char_type* - time_input_facet::default_time_duration_format = time_formats::default_time_duration_format; - -} } // namespaces - -#endif diff --git a/boost/date_time/time_formatting_streams.hpp b/boost/date_time/time_formatting_streams.hpp deleted file mode 100644 index f69f87a..0000000 --- a/boost/date_time/time_formatting_streams.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ -#define DATE_TIME_TIME_FORMATTING_STREAMS_HPP___ - -/* Copyright (c) 2002,2003 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include - -#ifndef BOOST_DATE_TIME_NO_LOCALE - -#include -#include -#include -#include -#include - -namespace boost { -namespace date_time { - - - //! Put a time type into a stream using appropriate facets - template - class ostream_time_duration_formatter - { - public: - typedef std::basic_ostream ostream_type; - typedef typename time_duration_type::fractional_seconds_type fractional_seconds_type; - - //! Put time into an ostream - static void duration_put(const time_duration_type& td, - ostream_type& os) - { - if(td.is_special()) { - os << td.get_rep(); - } - else { - charT fill_char = '0'; - if(td.is_negative()) { - os << '-'; - } - os << std::setw(2) << std::setfill(fill_char) - << absolute_value(td.hours()) << ":"; - os << std::setw(2) << std::setfill(fill_char) - << absolute_value(td.minutes()) << ":"; - os << std::setw(2) << std::setfill(fill_char) - << absolute_value(td.seconds()); - fractional_seconds_type frac_sec = - absolute_value(td.fractional_seconds()); - if (frac_sec != 0) { - os << "." - << std::setw(time_duration_type::num_fractional_digits()) - << std::setfill(fill_char) - << frac_sec; - } - } // else - } // duration_put - }; //class ostream_time_duration_formatter - - //! Put a time type into a stream using appropriate facets - template - class ostream_time_formatter - { - public: - typedef std::basic_ostream ostream_type; - typedef typename time_type::date_type date_type; - typedef typename time_type::time_duration_type time_duration_type; - typedef ostream_time_duration_formatter duration_formatter; - - //! Put time into an ostream - static void time_put(const time_type& t, - ostream_type& os) - { - date_type d = t.date(); - os << d; - if(!d.is_infinity() && !d.is_not_a_date()) - { - os << " "; //TODO: fix the separator here. - duration_formatter::duration_put(t.time_of_day(), os); - } - - } // time_to_ostream - }; //class ostream_time_formatter - - - //! Put a time period into a stream using appropriate facets - template - class ostream_time_period_formatter - { - public: - typedef std::basic_ostream ostream_type; - typedef typename time_period_type::point_type time_type; - typedef ostream_time_formatter time_formatter; - - //! Put time into an ostream - static void period_put(const time_period_type& tp, - ostream_type& os) - { - os << '['; //TODO: facet or manipulator for periods? - time_formatter::time_put(tp.begin(), os); - os << '/'; //TODO: facet or manipulator for periods? - time_formatter::time_put(tp.last(), os); - os << ']'; - - } // period_put - - }; //class ostream_time_period_formatter - - - -} } //namespace date_time - -#endif //BOOST_DATE_TIME_NO_LOCALE - -#endif diff --git a/boost/date_time/time_parsing.hpp b/boost/date_time/time_parsing.hpp deleted file mode 100644 index 98bedbf..0000000 --- a/boost/date_time/time_parsing.hpp +++ /dev/null @@ -1,339 +0,0 @@ -#ifndef _DATE_TIME_TIME_PARSING_HPP___ -#define _DATE_TIME_TIME_PARSING_HPP___ - -/* Copyright (c) 2002,2003,2005 CrystalClear Software, Inc. - * Use, modification and distribution is subject to the - * Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) - * Author: Jeff Garland, Bart Garst - * $Date$ - */ - -#include "boost/tokenizer.hpp" -#include "boost/lexical_cast.hpp" -#include "boost/date_time/date_parsing.hpp" -#include "boost/date_time/special_values_parser.hpp" -#include "boost/cstdint.hpp" -#include - -namespace boost { -namespace date_time { - - //! computes exponential math like 2^8 => 256, only works with positive integers - //Not general purpose, but needed b/c std::pow is not available - //everywhere. Hasn't been tested with negatives and zeros - template - inline - int_type power(int_type base, int_type exponent) - { - int_type result = 1; - for(int i = 0; i < exponent; ++i){ - result *= base; - } - return result; - } - - //! Creates a time_duration object from a delimited string - /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". - * If the number of fractional digits provided is greater than the - * precision of the time duration type then the extra digits are - * truncated. - * - * A negative duration will be created if the first character in - * string is a '-', all other '-' will be treated as delimiters. - * Accepted delimiters are "-:,.". - */ - template - inline - time_duration - str_from_delimited_time_duration(const std::basic_string& s) - { - unsigned short min=0, sec =0; - int hour =0; - bool is_neg = (s.at(0) == '-'); - boost::int64_t fs=0; - int pos = 0; - - typedef typename std::basic_string::traits_type traits_type; - typedef boost::char_separator char_separator_type; - typedef boost::tokenizer::const_iterator, - std::basic_string > tokenizer; - typedef typename boost::tokenizer::const_iterator, - typename std::basic_string >::iterator tokenizer_iterator; - - char_type sep_chars[5] = {'-',':',',','.'}; - char_separator_type sep(sep_chars); - tokenizer tok(s,sep); - for(tokenizer_iterator beg=tok.begin(); beg!=tok.end();++beg){ - switch(pos) { - case 0: { - hour = boost::lexical_cast(*beg); - break; - } - case 1: { - min = boost::lexical_cast(*beg); - break; - } - case 2: { - sec = boost::lexical_cast(*beg); - break; - } - case 3: { - int digits = static_cast(beg->length()); - //Works around a bug in MSVC 6 library that does not support - //operator>> thus meaning lexical_cast will fail to compile. -#if (defined(BOOST_MSVC) && (_MSC_VER < 1300)) - // msvc wouldn't compile 'time_duration::num_fractional_digits()' - // (required template argument list) as a workaround a temp - // time_duration object was used - time_duration td(hour,min,sec,fs); - int precision = td.num_fractional_digits(); - // _atoi64 is an MS specific function - if(digits >= precision) { - // drop excess digits - fs = _atoi64(beg->substr(0, precision).c_str()); - } - else { - fs = _atoi64(beg->c_str()); - } -#else - int precision = time_duration::num_fractional_digits(); - if(digits >= precision) { - // drop excess digits - fs = boost::lexical_cast(beg->substr(0, precision)); - } - else { - fs = boost::lexical_cast(*beg); - } -#endif - if(digits < precision){ - // trailing zeros get dropped from the string, - // "1:01:01.1" would yield .000001 instead of .100000 - // the power() compensates for the missing decimal places - fs *= power(10, precision - digits); - } - - break; - } - default: break; - }//switch - pos++; - } - if(is_neg) { - return -time_duration(hour, min, sec, fs); - } - else { - return time_duration(hour, min, sec, fs); - } - } - - //! Creates a time_duration object from a delimited string - /*! Expected format for string is "[-]h[h][:mm][:ss][.fff]". - * If the number of fractional digits provided is greater than the - * precision of the time duration type then the extra digits are - * truncated. - * - * A negative duration will be created if the first character in - * string is a '-', all other '-' will be treated as delimiters. - * Accepted delimiters are "-:,.". - */ - template - inline - time_duration - parse_delimited_time_duration(const std::string& s) - { - return str_from_delimited_time_duration(s); - } - - //! Utility function to split appart string - inline - bool - split(const std::string& s, - char sep, - std::string& first, - std::string& second) - { - std::string::size_type sep_pos = s.find(sep); - first = s.substr(0,sep_pos); - if (sep_pos!=std::string::npos) - second = s.substr(sep_pos+1); - return true; - } - - - template - inline - time_type - parse_delimited_time(const std::string& s, char sep) - { - typedef typename time_type::time_duration_type time_duration; - typedef typename time_type::date_type date_type; - - //split date/time on a unique delimiter char such as ' ' or 'T' - std::string date_string, tod_string; - split(s, sep, date_string, tod_string); - //call parse_date with first string - date_type d = parse_date(date_string); - //call parse_time_duration with remaining string - time_duration td = parse_delimited_time_duration(tod_string); - //construct a time - return time_type(d, td); - - } - - //! Parse time duration part of an ISO 8601 time of form: [-]hhmmss[.fff...] (eg: 120259.123 is 12 hours, 2 min, 59 seconds, 123000 microseconds) - template - inline - time_duration - parse_undelimited_time_duration(const std::string& s) - { - int precision = 0; - { - // msvc wouldn't compile 'time_duration::num_fractional_digits()' - // (required template argument list) as a workaround, a temp - // time_duration object was used - time_duration tmp(0,0,0,1); - precision = tmp.num_fractional_digits(); - } - // 'precision+1' is so we grab all digits, plus the decimal - int offsets[] = {2,2,2, precision+1}; - int pos = 0, sign = 0; - int hours = 0; - short min=0, sec=0; - boost::int64_t fs=0; - // increment one position if the string was "signed" - if(s.at(sign) == '-') - { - ++sign; - } - // stlport choked when passing s.substr() to tokenizer - // using a new string fixed the error - std::string remain = s.substr(sign); - /* We do not want the offset_separator to wrap the offsets, we - * will never want to process more than: - * 2 char, 2 char, 2 char, frac_sec length. - * We *do* want the offset_separator to give us a partial for the - * last characters if there were not enough provided in the input string. */ - bool wrap_off = false; - bool ret_part = true; - boost::offset_separator osf(offsets, offsets+4, wrap_off, ret_part); - typedef boost::tokenizer::const_iterator, - std::basic_string > tokenizer; - typedef boost::tokenizer::const_iterator, - std::basic_string >::iterator tokenizer_iterator; - tokenizer tok(remain, osf); - for(tokenizer_iterator ti=tok.begin(); ti!=tok.end();++ti){ - switch(pos) { - case 0: - { - hours = boost::lexical_cast(*ti); - break; - } - case 1: - { - min = boost::lexical_cast(*ti); - break; - } - case 2: - { - sec = boost::lexical_cast(*ti); - break; - } - case 3: - { - std::string char_digits(ti->substr(1)); // digits w/no decimal - int digits = static_cast(char_digits.length()); - - //Works around a bug in MSVC 6 library that does not support - //operator>> thus meaning lexical_cast will fail to compile. -#if (defined(BOOST_MSVC) && (_MSC_VER <= 1200)) // 1200 == VC++ 6.0 - // _atoi64 is an MS specific function - if(digits >= precision) { - // drop excess digits - fs = _atoi64(char_digits.substr(0, precision).c_str()); - } - else if(digits == 0) { - fs = 0; // just in case _atoi64 doesn't like an empty string - } - else { - fs = _atoi64(char_digits.c_str()); - } -#else - if(digits >= precision) { - // drop excess digits - fs = boost::lexical_cast(char_digits.substr(0, precision)); - } - else if(digits == 0) { - fs = 0; // lexical_cast doesn't like empty strings - } - else { - fs = boost::lexical_cast(char_digits); - } -#endif - if(digits < precision){ - // trailing zeros get dropped from the string, - // "1:01:01.1" would yield .000001 instead of .100000 - // the power() compensates for the missing decimal places - fs *= power(10, precision - digits); - } - - break; - } - default: break; - } - pos++; - } - if(sign) { - return -time_duration(hours, min, sec, fs); - } - else { - return time_duration(hours, min, sec, fs); - } - } - - //! Parse time string of form YYYYMMDDThhmmss where T is delimeter between date and time - template - inline - time_type - parse_iso_time(const std::string& s, char sep) - { - typedef typename time_type::time_duration_type time_duration; - typedef typename time_type::date_type date_type; - typedef special_values_parser svp_type; - - // given to_iso_string can produce a special value string - // then from_iso_string should be able to read a special value string - // the special_values_parser is expensive to set up and not thread-safe - // so it cannot be static, so we need to be careful about when we use it - if (svp_type::should_call_match(s)) { - typedef typename svp_type::stringstream_type ss_type; - typedef typename svp_type::stream_itr_type itr_type; - typedef typename svp_type::match_results mr_type; - svp_type p; // expensive - mr_type mr; - ss_type ss(s); - itr_type itr(ss); - itr_type end; - if (p.match(itr, end, mr)) { - return time_type(static_cast(mr.current_match)); - } - } - - //split date/time on a unique delimiter char such as ' ' or 'T' - std::string date_string, tod_string; - split(s, sep, date_string, tod_string); - //call parse_date with first string - date_type d = parse_undelimited_date(date_string); - //call parse_time_duration with remaining string - time_duration td = parse_undelimited_time_duration(tod_string); - //construct a time - return time_type(d, td); - } - -} }//namespace date_time - -#endif diff --git a/boost/describe/members.hpp b/boost/describe/members.hpp index bce49db..828c495 100644 --- a/boost/describe/members.hpp +++ b/boost/describe/members.hpp @@ -86,9 +86,11 @@ template struct update_modifiers }; }; +#ifndef __cpp_inline_variables template template constexpr decltype(D::pointer) update_modifiers::fn::pointer; template template constexpr decltype(D::name) update_modifiers::fn::name; template template constexpr unsigned update_modifiers::fn::modifiers; +#endif template struct gather_virtual_bases_impl; template using gather_virtual_bases = typename gather_virtual_bases_impl::type; diff --git a/boost/detail/basic_pointerbuf.hpp b/boost/detail/basic_pointerbuf.hpp deleted file mode 100644 index a92a489..0000000 --- a/boost/detail/basic_pointerbuf.hpp +++ /dev/null @@ -1,138 +0,0 @@ -//----------------------------------------------------------------------------- -// boost detail/templated_streams.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2013 John Maddock, Antony Polukhin -// -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_DETAIL_BASIC_POINTERBUF_HPP -#define BOOST_DETAIL_BASIC_POINTERBUF_HPP - -// MS compatible compilers support #pragma once -#if defined(_MSC_VER) -# pragma once -#endif - -#include "boost/config.hpp" -#include - -namespace boost { namespace detail { - -// -// class basic_pointerbuf: -// acts as a stream buffer which wraps around a pair of pointers: -// -template -class basic_pointerbuf : public BufferT { -protected: - typedef BufferT base_type; - typedef basic_pointerbuf this_type; - typedef typename base_type::int_type int_type; - typedef typename base_type::char_type char_type; - typedef typename base_type::pos_type pos_type; - typedef ::std::streamsize streamsize; - typedef typename base_type::off_type off_type; - -public: - basic_pointerbuf() : base_type() { this_type::setbuf(0, 0); } - const charT* getnext() { return this->gptr(); } - -#ifndef BOOST_NO_USING_TEMPLATE - using base_type::pptr; - using base_type::pbase; -#else - charT* pptr() const { return base_type::pptr(); } - charT* pbase() const { return base_type::pbase(); } -#endif - -protected: - // VC mistakenly assumes that `setbuf` and other functions are not referenced. - // Marking those functions with `inline` suppresses the warnings. - // There must be no harm from marking virtual functions as inline: inline virtual - // call can be inlined ONLY when the compiler knows the "exact class". - inline base_type* setbuf(char_type* s, streamsize n) BOOST_OVERRIDE; - inline typename this_type::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) BOOST_OVERRIDE; - inline typename this_type::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) BOOST_OVERRIDE; - -private: - basic_pointerbuf& operator=(const basic_pointerbuf&); - basic_pointerbuf(const basic_pointerbuf&); -}; - -template -BufferT* -basic_pointerbuf::setbuf(char_type* s, streamsize n) -{ - this->setg(s, s, s + n); - return this; -} - -template -typename basic_pointerbuf::pos_type -basic_pointerbuf::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) -{ - typedef typename boost::int_t::least cast_type; - - if(which & ::std::ios_base::out) - return pos_type(off_type(-1)); - std::ptrdiff_t size = this->egptr() - this->eback(); - std::ptrdiff_t pos = this->gptr() - this->eback(); - charT* g = this->eback(); - switch(static_cast(way)) - { - case ::std::ios_base::beg: - if((off < 0) || (off > size)) - return pos_type(off_type(-1)); - else - this->setg(g, g + off, g + size); - break; - case ::std::ios_base::end: - if((off < 0) || (off > size)) - return pos_type(off_type(-1)); - else - this->setg(g, g + size - off, g + size); - break; - case ::std::ios_base::cur: - { - std::ptrdiff_t newpos = static_cast(pos + off); - if((newpos < 0) || (newpos > size)) - return pos_type(off_type(-1)); - else - this->setg(g, g + newpos, g + size); - break; - } - default: ; - } -#ifdef BOOST_MSVC -#pragma warning(push) -#pragma warning(disable:4244) -#endif - return static_cast(this->gptr() - this->eback()); -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif -} - -template -typename basic_pointerbuf::pos_type -basic_pointerbuf::seekpos(pos_type sp, ::std::ios_base::openmode which) -{ - if(which & ::std::ios_base::out) - return pos_type(off_type(-1)); - off_type size = static_cast(this->egptr() - this->eback()); - charT* g = this->eback(); - if(off_type(sp) <= size) - { - this->setg(g, g + off_type(sp), g + size); - } - return pos_type(off_type(-1)); -} - -}} // namespace boost::detail - -#endif // BOOST_DETAIL_BASIC_POINTERBUF_HPP diff --git a/boost/detail/bitmask.hpp b/boost/detail/bitmask.hpp new file mode 100644 index 0000000..63d4fac --- /dev/null +++ b/boost/detail/bitmask.hpp @@ -0,0 +1,58 @@ +// boost/detail/bitmask.hpp ------------------------------------------------// + +// Copyright Beman Dawes 2006 + +// Distributed under the Boost Software License, Version 1.0 +// http://www.boost.org/LICENSE_1_0.txt + +// Usage: enum foo { a=1, b=2, c=4 }; +// BOOST_BITMASK( foo ) +// +// void f( foo arg ); +// ... +// f( a | c ); +// +// See [bitmask.types] in the C++ standard for the formal specification + +#ifndef BOOST_BITMASK_HPP +#define BOOST_BITMASK_HPP + +#include +#include + +#define BOOST_BITMASK(Bitmask) \ + \ + inline BOOST_CONSTEXPR Bitmask operator| (Bitmask x , Bitmask y ) \ + { return static_cast( static_cast(x) \ + | static_cast(y)); } \ + \ + inline BOOST_CONSTEXPR Bitmask operator& (Bitmask x , Bitmask y ) \ + { return static_cast( static_cast(x) \ + & static_cast(y)); } \ + \ + inline BOOST_CONSTEXPR Bitmask operator^ (Bitmask x , Bitmask y ) \ + { return static_cast( static_cast(x) \ + ^ static_cast(y)); } \ + \ + inline BOOST_CONSTEXPR Bitmask operator~ (Bitmask x ) \ + { return static_cast(~static_cast(x)); } \ + \ + inline Bitmask & operator&=(Bitmask& x , Bitmask y) \ + { x = x & y ; return x ; } \ + \ + inline Bitmask & operator|=(Bitmask& x , Bitmask y) \ + { x = x | y ; return x ; } \ + \ + inline Bitmask & operator^=(Bitmask& x , Bitmask y) \ + { x = x ^ y ; return x ; } \ + \ + /* Boost extensions to [bitmask.types] */ \ + \ + inline BOOST_CONSTEXPR bool operator!(Bitmask x) \ + { return !static_cast(x); } \ + \ + inline BOOST_CONSTEXPR bool bitmask_set(Bitmask x) \ + { return !!x; } + +#endif // BOOST_BITMASK_HPP + diff --git a/boost/detail/is_sorted.hpp b/boost/detail/is_sorted.hpp deleted file mode 100644 index 84357f9..0000000 --- a/boost/detail/is_sorted.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/*============================================================================== - Copyright (c) 2010-2011 Bryce Lelbach - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -==============================================================================*/ - -#ifndef BOOST_DETAIL_SORTED_HPP -#define BOOST_DETAIL_SORTED_HPP - -#include -#include - -namespace boost { -namespace detail { - -template -inline Iterator is_sorted_until (Iterator first, Iterator last, Comp c) { - if (first == last) - return last; - - Iterator it = first; ++it; - - for (; it != last; first = it, ++it) - if (c(*it, *first)) - return it; - - return it; -} - -template -inline Iterator is_sorted_until (Iterator first, Iterator last) { - typedef typename std::iterator_traits::value_type - value_type; - - typedef std::less c; - - return ::boost::detail::is_sorted_until(first, last, c()); -} - -template -inline bool is_sorted (Iterator first, Iterator last, Comp c) { - return ::boost::detail::is_sorted_until(first, last, c) == last; -} - -template -inline bool is_sorted (Iterator first, Iterator last) { - return ::boost::detail::is_sorted_until(first, last) == last; -} - -} // detail -} // boost - -#endif // BOOST_DETAIL_SORTED_HPP - diff --git a/boost/detail/lcast_precision.hpp b/boost/detail/lcast_precision.hpp deleted file mode 100644 index 84bf122..0000000 --- a/boost/detail/lcast_precision.hpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright Alexander Nasonov & Paul A. Bristow 2006. - -// Use, modification and distribution are subject to the -// Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED -#define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED - -#include -#include -#include - -#include -#include - -#ifndef BOOST_NO_IS_ABSTRACT -// Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL -#include -#include -#endif - -#if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || \ - (defined(BOOST_MSVC) && (BOOST_MSVC<1310)) - -#define BOOST_LCAST_NO_COMPILE_TIME_PRECISION -#endif - -#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION -#include -#else -#include -#endif - -namespace boost { namespace detail { - -class lcast_abstract_stub {}; - -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION -// Calculate an argument to pass to std::ios_base::precision from -// lexical_cast. See alternative implementation for broken standard -// libraries in lcast_get_precision below. Keep them in sync, please. -template -struct lcast_precision -{ -#ifdef BOOST_NO_IS_ABSTRACT - typedef std::numeric_limits limits; // No fix for SF:1358600. -#else - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_abstract::value - , std::numeric_limits - , std::numeric_limits - >::type limits; -#endif - - BOOST_STATIC_CONSTANT(bool, use_default_precision = - !limits::is_specialized || limits::is_exact - ); - - BOOST_STATIC_CONSTANT(bool, is_specialized_bin = - !use_default_precision && - limits::radix == 2 && limits::digits > 0 - ); - - BOOST_STATIC_CONSTANT(bool, is_specialized_dec = - !use_default_precision && - limits::radix == 10 && limits::digits10 > 0 - ); - - BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max = - boost::integer_traits::const_max - ); - - BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U); - - BOOST_STATIC_ASSERT(!is_specialized_dec || - precision_dec <= streamsize_max + 0UL - ); - - BOOST_STATIC_CONSTANT(unsigned long, precision_bin = - 2UL + limits::digits * 30103UL / 100000UL - ); - - BOOST_STATIC_ASSERT(!is_specialized_bin || - (limits::digits + 0UL < ULONG_MAX / 30103UL && - precision_bin > limits::digits10 + 0UL && - precision_bin <= streamsize_max + 0UL) - ); - - BOOST_STATIC_CONSTANT(std::streamsize, value = - is_specialized_bin ? precision_bin - : is_specialized_dec ? precision_dec : 6 - ); -}; -#endif - -template -inline std::streamsize lcast_get_precision(T* = 0) -{ -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - return lcast_precision::value; -#else // Follow lcast_precision algorithm at run-time: - -#ifdef BOOST_NO_IS_ABSTRACT - typedef std::numeric_limits limits; // No fix for SF:1358600. -#else - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_abstract::value - , std::numeric_limits - , std::numeric_limits - >::type limits; -#endif - - bool const use_default_precision = - !limits::is_specialized || limits::is_exact; - - if(!use_default_precision) - { // Includes all built-in floating-point types, float, double ... - // and UDT types for which digits (significand bits) is defined (not zero) - - bool const is_specialized_bin = - limits::radix == 2 && limits::digits > 0; - bool const is_specialized_dec = - limits::radix == 10 && limits::digits10 > 0; - std::streamsize const streamsize_max = - (boost::integer_traits::max)(); - (void)streamsize_max; - - if(is_specialized_bin) - { // Floating-point types with - // limits::digits defined by the specialization. - - unsigned long const digits = limits::digits; - unsigned long const precision = 2UL + digits * 30103UL / 100000UL; - // unsigned long is selected because it is at least 32-bits - // and thus ULONG_MAX / 30103UL is big enough for all types. - BOOST_ASSERT( - digits < ULONG_MAX / 30103UL && - precision > limits::digits10 + 0UL && - precision <= streamsize_max + 0UL - ); - return precision; - } - else if(is_specialized_dec) - { // Decimal Floating-point type, most likely a User Defined Type - // rather than a real floating-point hardware type. - unsigned int const precision = limits::digits10 + 1U; - BOOST_ASSERT(precision <= streamsize_max + 0UL); - return precision; - } - } - - // Integral type (for which precision has no effect) - // or type T for which limits is NOT specialized, - // so assume stream precision remains the default 6 decimal digits. - // Warning: if your User-defined Floating-point type T is NOT specialized, - // then you may lose accuracy by only using 6 decimal digits. - // To avoid this, you need to specialize T with either - // radix == 2 and digits == the number of significand bits, - // OR - // radix = 10 and digits10 == the number of decimal digits. - - return 6; -#endif -} - -template -inline void lcast_set_precision(std::ios_base& stream, T*) -{ - stream.precision(lcast_get_precision()); -} - -template -inline void lcast_set_precision(std::ios_base& stream, Source*, Target*) -{ - std::streamsize const s = lcast_get_precision(static_cast(0)); - std::streamsize const t = lcast_get_precision(static_cast(0)); - stream.precision(s > t ? s : t); -} - -}} - -#endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED - diff --git a/boost/detail/templated_streams.hpp b/boost/detail/templated_streams.hpp deleted file mode 100644 index 1fa6ee3..0000000 --- a/boost/detail/templated_streams.hpp +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// boost detail/templated_streams.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_DETAIL_TEMPLATED_STREAMS_HPP -#define BOOST_DETAIL_TEMPLATED_STREAMS_HPP - -#include "boost/config.hpp" - -/////////////////////////////////////////////////////////////////////////////// -// (detail) BOOST_TEMPLATED_STREAM_* macros -// -// Provides workaround platforms without stream class templates. -// - -#if !defined(BOOST_NO_STD_LOCALE) - -#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) \ - template < typename E , typename T > - -#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) \ - template < typename E , typename T , typename A > - -#define BOOST_TEMPLATED_STREAM_ARGS(E,T) \ - typename E , typename T - -#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) \ - typename E , typename T , typename A - -#define BOOST_TEMPLATED_STREAM_COMMA , - -#define BOOST_TEMPLATED_STREAM_ELEM(E) E -#define BOOST_TEMPLATED_STREAM_TRAITS(T) T -#define BOOST_TEMPLATED_STREAM_ALLOC(A) A - -#define BOOST_TEMPLATED_STREAM(X,E,T) \ - BOOST_JOIN(std::basic_,X)< E , T > - -#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \ - BOOST_JOIN(std::basic_,X)< E , T , A > - -#else // defined(BOOST_NO_STD_LOCALE) - -#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) /**/ - -#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) /**/ - -#define BOOST_TEMPLATED_STREAM_ARGS(E,T) /**/ - -#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) /**/ - -#define BOOST_TEMPLATED_STREAM_COMMA /**/ - -#define BOOST_TEMPLATED_STREAM_ELEM(E) char -#define BOOST_TEMPLATED_STREAM_TRAITS(T) std::char_traits -#define BOOST_TEMPLATED_STREAM_ALLOC(A) std::allocator - -#define BOOST_TEMPLATED_STREAM(X,E,T) \ - std::X - -#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \ - std::X - -#endif // BOOST_NO_STD_LOCALE - -#endif // BOOST_DETAIL_TEMPLATED_STREAMS_HPP diff --git a/boost/filesystem.hpp b/boost/filesystem.hpp new file mode 100644 index 0000000..36bf907 --- /dev/null +++ b/boost/filesystem.hpp @@ -0,0 +1,26 @@ +// boost/filesystem.hpp --------------------------------------------------------------// + +// Copyright Beman Dawes 2010 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_FILESYSTEM_HPP +#define BOOST_FILESYSTEM_FILESYSTEM_HPP + +#include +#include +#include +#include +#include +#include +#include +#if defined(BOOST_FILESYSTEM_DEPRECATED) +#include +#endif + +#endif // BOOST_FILESYSTEM_FILESYSTEM_HPP diff --git a/boost/filesystem/config.hpp b/boost/filesystem/config.hpp new file mode 100644 index 0000000..cf7584a --- /dev/null +++ b/boost/filesystem/config.hpp @@ -0,0 +1,152 @@ +// boost/filesystem/v3/config.hpp ----------------------------------------------------// + +// Copyright Beman Dawes 2003 +// Copyright Andrey Semashev 2021-2023 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_CONFIG_HPP +#define BOOST_FILESYSTEM_CONFIG_HPP + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include +#include // for BOOST_POSIX_API or BOOST_WINDOWS_API +#include + +#if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION != 3 && BOOST_FILESYSTEM_VERSION != 4 +#error Compiling Boost.Filesystem file with BOOST_FILESYSTEM_VERSION defined != 3 or 4 +#endif + +#if defined(BOOST_FILESYSTEM_SOURCE) +#undef BOOST_FILESYSTEM_VERSION +#define BOOST_FILESYSTEM_VERSION 4 +#elif !defined(BOOST_FILESYSTEM_VERSION) +#define BOOST_FILESYSTEM_VERSION 3 +#endif + +#define BOOST_FILESYSTEM_VERSIONED_SYM(sym) BOOST_JOIN(sym, BOOST_JOIN(_v, BOOST_FILESYSTEM_VERSION)) + +#if BOOST_FILESYSTEM_VERSION == 4 +#undef BOOST_FILESYSTEM_DEPRECATED +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +#define BOOST_FILESYSTEM_NO_DEPRECATED +#endif +#endif + +#define BOOST_FILESYSTEM_I18N // aid users wishing to compile several versions + +// BOOST_FILESYSTEM_DEPRECATED needed for source compiles -----------------------------// + +#ifdef BOOST_FILESYSTEM_SOURCE +#define BOOST_FILESYSTEM_DEPRECATED +#undef BOOST_FILESYSTEM_NO_DEPRECATED // fixes #9454, src bld fails if NO_DEP defined +#endif + +#if defined(BOOST_FILESYSTEM_DEPRECATED) && defined(BOOST_FILESYSTEM_NO_DEPRECATED) +#error Both BOOST_FILESYSTEM_DEPRECATED and BOOST_FILESYSTEM_NO_DEPRECATED are defined +#endif + +// throw an exception ----------------------------------------------------------------// +// +// Exceptions were originally thrown via boost::throw_exception(). +// As throw_exception() became more complex, it caused user error reporting +// to be harder to interpret, since the exception reported became much more complex. +// The immediate fix was to throw directly, wrapped in a macro to make any later change +// easier. + +#define BOOST_FILESYSTEM_THROW(EX) throw EX + +#if defined(BOOST_NO_STD_WSTRING) +#error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support +#endif + +// Deprecated symbols markup -----------------------------------------------------------// + +#if !defined(BOOST_FILESYSTEM_ALLOW_DEPRECATED) +#define BOOST_FILESYSTEM_DETAIL_DEPRECATED(msg) BOOST_DEPRECATED(msg) +#else +#define BOOST_FILESYSTEM_DETAIL_DEPRECATED(msg) +#endif + + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// normalize macros ------------------------------------------------------------------// + +#if !defined(BOOST_FILESYSTEM_DYN_LINK) && !defined(BOOST_FILESYSTEM_STATIC_LINK) && !defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_ALL_STATIC_LINK) +#define BOOST_FILESYSTEM_STATIC_LINK +#endif + +#if defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_FILESYSTEM_DYN_LINK) +#define BOOST_FILESYSTEM_DYN_LINK +#elif defined(BOOST_ALL_STATIC_LINK) && !defined(BOOST_FILESYSTEM_STATIC_LINK) +#define BOOST_FILESYSTEM_STATIC_LINK +#endif + +#if defined(BOOST_FILESYSTEM_DYN_LINK) && defined(BOOST_FILESYSTEM_STATIC_LINK) +#error Must not define both BOOST_FILESYSTEM_DYN_LINK and BOOST_FILESYSTEM_STATIC_LINK +#endif + +#if defined(BOOST_ALL_NO_LIB) && !defined(BOOST_FILESYSTEM_NO_LIB) +#define BOOST_FILESYSTEM_NO_LIB +#endif + +// enable dynamic linking ------------------------------------------------------------// + +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK) +#if defined(BOOST_FILESYSTEM_SOURCE) +#define BOOST_FILESYSTEM_DECL BOOST_SYMBOL_EXPORT +#else +#define BOOST_FILESYSTEM_DECL BOOST_SYMBOL_IMPORT +#endif +#else +#define BOOST_FILESYSTEM_DECL +#endif + +// enable automatic library variant selection ----------------------------------------// + +#if !defined(BOOST_FILESYSTEM_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_FILESYSTEM_NO_LIB) +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_filesystem +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK) +#define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) ||\ + (defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 50000)) ||\ + (defined(BOOST_MSSTL_VERSION) && (BOOST_MSSTL_VERSION < 100)) +// Indicates that the standard library fstream types do not support move constructor/assignment. +#define BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS +#endif + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) && \ + (\ + (defined(BOOST_DINKUMWARE_STDLIB) && defined(_HAS_CXX23) && (_HAS_CXX23 != 0) && defined(_MSVC_STL_UPDATE) && (_MSVC_STL_UPDATE < 202208L)) || \ + (defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 110400 || (BOOST_LIBSTDCXX_VERSION >= 120000 && BOOST_LIBSTDCXX_VERSION < 120200)) && (BOOST_CXX_VERSION > 202002L))\ + ) +// Indicates that std::string_view has implicit constructor from ranges that was present in an early C++23 draft (N4892). +// This was later rectified by marking the constructor explicit (https://wg21.link/p2499). Unfortunately, some compilers +// were released with the constructor being implicit. +#define BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR +#endif + +#endif // BOOST_FILESYSTEM_CONFIG_HPP diff --git a/boost/filesystem/convenience.hpp b/boost/filesystem/convenience.hpp new file mode 100644 index 0000000..d66add2 --- /dev/null +++ b/boost/filesystem/convenience.hpp @@ -0,0 +1,55 @@ +// boost/filesystem/convenience.hpp ----------------------------------------// + +// Copyright Beman Dawes, 2002-2005 +// Copyright Vladimir Prus, 2002 + +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/filesystem + +//----------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_CONVENIENCE_HPP +#define BOOST_FILESYSTEM_CONVENIENCE_HPP + +#include +#include +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::extension() instead") +inline std::string extension(const path& p) +{ + return p.extension().string(); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::stem() instead") +inline std::string basename(const path& p) +{ + return p.stem().string(); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::replace_extension() instead") +inline path change_extension(const path& p, const path& new_extension) +{ + path new_p(p); + new_p.replace_extension(new_extension); + return new_p; +} + +#endif + +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_CONVENIENCE_HPP diff --git a/boost/filesystem/detail/footer.hpp b/boost/filesystem/detail/footer.hpp new file mode 100644 index 0000000..ce4bc1f --- /dev/null +++ b/boost/filesystem/detail/footer.hpp @@ -0,0 +1,23 @@ +/* + * Copyright Andrey Semashev 2021. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#if !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS) + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) + +#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \ + && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__) + +#pragma GCC diagnostic pop + +#endif + +#endif // !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS) + +#include diff --git a/boost/filesystem/detail/header.hpp b/boost/filesystem/detail/header.hpp new file mode 100644 index 0000000..f98b0ab --- /dev/null +++ b/boost/filesystem/detail/header.hpp @@ -0,0 +1,54 @@ +/* + * Copyright Andrey Semashev 2021. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include + +#if !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS) + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(push, 3) +// 'm_A' : class 'A' needs to have dll-interface to be used by clients of class 'B' +#pragma warning(disable: 4251) +// non dll-interface class 'A' used as base for dll-interface class 'B' +#pragma warning(disable: 4275) +// 'int' : forcing value to bool 'true' or 'false' (performance warning) +#pragma warning(disable: 4800) +// unreferenced formal parameter +#pragma warning(disable: 4100) +// conditional expression is constant +#pragma warning(disable: 4127) +// function marked as __forceinline not inlined +#pragma warning(disable: 4714) +// decorated name length exceeded, name was truncated +#pragma warning(disable: 4503) +// 'X': This function or variable may be unsafe. Consider using Y instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. +#pragma warning(disable: 4996) +// qualifier applied to function type has no meaning; ignored +#pragma warning(disable: 4180) +// qualifier applied to reference type; ignored +#pragma warning(disable: 4181) + +#elif (defined(__GNUC__) && !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) \ + && (__GNUC__ * 100 + __GNUC_MINOR__) >= 406) || defined(__clang__) + +// Note: clang-cl goes here as well, as it seems to support gcc-style warning control pragmas. + +#pragma GCC diagnostic push +// unused parameter 'arg' +#pragma GCC diagnostic ignored "-Wunused-parameter" +// unused function 'foo' +#pragma GCC diagnostic ignored "-Wunused-function" + +#if defined(__clang__) +// template argument uses unnamed type +#pragma clang diagnostic ignored "-Wunnamed-type-template-args" +#endif // defined(__clang__) + +#endif + +#endif // !defined(BOOST_FILESYSTEM_ENABLE_WARNINGS) diff --git a/boost/filesystem/detail/path_traits.hpp b/boost/filesystem/detail/path_traits.hpp new file mode 100644 index 0000000..562b967 --- /dev/null +++ b/boost/filesystem/detail/path_traits.hpp @@ -0,0 +1,737 @@ +// filesystem path_traits.hpp --------------------------------------------------------// + +// Copyright Beman Dawes 2009 +// Copyright Andrey Semashev 2022 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#ifndef BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP +#define BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP + +#include +#include +#include // for strlen +#include // for mbstate_t, wcslen +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#if defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) +#include +#include +#endif +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4 +#include +#include +#endif + +#include // must be the last #include + +namespace boost { + +template< typename, typename > class basic_string_view; + +namespace container { +template< typename, typename, typename > class basic_string; +} // namespace container + +namespace filesystem { + +BOOST_FILESYSTEM_DECL system::error_category const& codecvt_error_category() BOOST_NOEXCEPT; + +class directory_entry; + +namespace detail { +namespace path_traits { + +#if defined(BOOST_WINDOWS_API) +typedef wchar_t path_native_char_type; +#define BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE false +#define BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE true +#else +typedef char path_native_char_type; +#define BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE true +#define BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE false +#endif + +typedef std::codecvt< wchar_t, char, std::mbstate_t > codecvt_type; + +struct unknown_type_tag {}; +struct ntcts_type_tag {}; +struct char_ptr_tag : ntcts_type_tag {}; +struct char_array_tag : ntcts_type_tag {}; +struct string_class_tag {}; +struct std_string_tag : string_class_tag {}; +struct boost_container_string_tag : string_class_tag {}; +struct std_string_view_tag : string_class_tag {}; +struct boost_string_view_tag : string_class_tag {}; +struct range_type_tag {}; +struct directory_entry_tag {}; + +//! The traits define a number of properties of a path source +template< typename T > +struct path_source_traits +{ + //! The kind of the path source. Useful for dispatching. + typedef unknown_type_tag tag_type; + //! Character type that the source contains + typedef void char_type; + //! Indicates whether the source is natively supported by \c path::string_type as arguments for constructors/assignment/appending + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct path_source_traits< char* > +{ + typedef char_ptr_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< const char* > +{ + typedef char_ptr_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< wchar_t* > +{ + typedef char_ptr_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< > +struct path_source_traits< const wchar_t* > +{ + typedef char_ptr_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< > +struct path_source_traits< char[] > +{ + typedef char_array_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< const char[] > +{ + typedef char_array_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< wchar_t[] > +{ + typedef char_array_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< > +struct path_source_traits< const wchar_t[] > +{ + typedef char_array_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< std::size_t N > +struct path_source_traits< char[N] > +{ + typedef char_array_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< std::size_t N > +struct path_source_traits< const char[N] > +{ + typedef char_array_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< std::size_t N > +struct path_source_traits< wchar_t[N] > +{ + typedef char_array_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< std::size_t N > +struct path_source_traits< const wchar_t[N] > +{ + typedef char_array_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< > +struct path_source_traits< std::string > +{ + typedef std_string_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< std::wstring > +{ + typedef std_string_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +template< > +struct path_source_traits< boost::container::basic_string< char, std::char_traits< char >, void > > +{ + typedef boost_container_string_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct path_source_traits< boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > > +{ + typedef boost_container_string_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + +template< > +struct path_source_traits< std::string_view > +{ + typedef std_string_view_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE; +}; + +template< > +struct path_source_traits< std::wstring_view > +{ + typedef std_string_view_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE; +}; + +#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + +template< > +struct path_source_traits< boost::basic_string_view< char, std::char_traits< char > > > +{ + typedef boost_string_view_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct path_source_traits< boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > > +{ + typedef boost_string_view_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4 +template< > +struct +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.") +path_source_traits< std::vector< char > > +{ + // Since C++11 this could be string_class_tag as std::vector gained data() member + typedef range_type_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.") +path_source_traits< std::vector< wchar_t > > +{ + // Since C++11 this could be string_class_tag as std::vector gained data() member + typedef range_type_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.") +path_source_traits< std::list< char > > +{ + typedef range_type_tag tag_type; + typedef char char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +template< > +struct +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Boost.Filesystem path construction/assignment/appending from containers is deprecated, use strings or iterators instead.") +path_source_traits< std::list< wchar_t > > +{ + typedef range_type_tag tag_type; + typedef wchar_t char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4 + +template< > +struct path_source_traits< directory_entry > +{ + typedef directory_entry_tag tag_type; + typedef path_native_char_type char_type; + static BOOST_CONSTEXPR_OR_CONST bool is_native = false; +}; + +#undef BOOST_FILESYSTEM_DETAIL_IS_CHAR_NATIVE +#undef BOOST_FILESYSTEM_DETAIL_IS_WCHAR_T_NATIVE + + +//! The trait tests if the type is a known path Source tag +template< typename Tag > +struct is_known_path_source_tag : + public boost::true_type +{ +}; + +template< > +struct is_known_path_source_tag< unknown_type_tag > : + public boost::false_type +{ +}; + +//! The trait tests if the type is compatible with path Source requirements +template< typename T > +struct is_path_source : + public is_known_path_source_tag< typename path_source_traits< T >::tag_type >::type +{ +}; + + +//! The trait indicates whether the type is a path Source that is natively supported by path::string_type as the source for construction/assignment/appending +template< typename T > +struct is_native_path_source : + public boost::integral_constant< bool, path_source_traits< T >::is_native > +{ +}; + + +//! The trait indicates whether the type is one of the supported path character types +template< typename T > +struct is_path_char_type : + public boost::false_type +{ +}; + +template< > +struct is_path_char_type< char > : + public boost::true_type +{ +}; + +template< > +struct is_path_char_type< wchar_t > : + public boost::true_type +{ +}; + + +template< typename Iterator > +struct is_iterator_to_path_chars : + public is_path_char_type< typename std::iterator_traits< Iterator >::value_type >::type +{ +}; + +//! The trait indicates whether the type is an iterator over a sequence of path characters +template< typename Iterator > +struct is_path_source_iterator : + public boost::conjunction< + boost::iterators::is_iterator< Iterator >, + is_iterator_to_path_chars< Iterator > + >::type +{ +}; + + +//! The trait indicates whether the type is a pointer to a sequence of native path characters +template< typename T > +struct is_native_char_ptr : + public boost::false_type +{ +}; + +template< > +struct is_native_char_ptr< path_native_char_type* > : + public boost::true_type +{ +}; + +template< > +struct is_native_char_ptr< const path_native_char_type* > : + public boost::true_type +{ +}; + + +//! Converts character encoding using the supplied codecvt facet. If \a cvt is \c NULL then \c path::codecvt() will be used. +BOOST_FILESYSTEM_DECL +void convert(const char* from, const char* from_end, std::wstring& to, const codecvt_type* cvt = NULL); + +//! \overload convert +BOOST_FILESYSTEM_DECL +void convert(const wchar_t* from, const wchar_t* from_end, std::string& to, const codecvt_type* cvt = NULL); + + +// Source dispatch -----------------------------------------------------------------// + +template< typename Source, typename Callback > +typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt = NULL); + +template< typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(const char* source, Callback cb, const codecvt_type* cvt, ntcts_type_tag) +{ + return cb(source, source + std::strlen(source), cvt); +} + +template< typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(const wchar_t* source, Callback cb, const codecvt_type* cvt, ntcts_type_tag) +{ + return cb(source, source + std::wcslen(source), cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt, string_class_tag) +{ + return cb(source.data(), source.data() + source.size(), cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt, range_type_tag) +{ + std::basic_string< typename Source::value_type > src(source.begin(), source.end()); + return cb(src.data(), src.data() + src.size(), cvt); +} + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4 + +template< typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(std::vector< char > const& source, Callback cb, const codecvt_type* cvt, range_type_tag) +{ + const char* data = NULL, *data_end = NULL; + if (!source.empty()) + { + data = &source[0]; + data_end = data + source.size(); + } + return cb(data, data_end, cvt); +} + +template< typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(std::vector< wchar_t > const& source, Callback cb, const codecvt_type* cvt, range_type_tag) +{ + const wchar_t* data = NULL, *data_end = NULL; + if (!source.empty()) + { + data = &source[0]; + data_end = data + source.size(); + } + return cb(data, data_end, cvt); +} + +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && BOOST_FILESYSTEM_VERSION < 4 + +// Defined in directory.hpp to avoid circular header dependencies +template< typename Callback > +typename Callback::result_type dispatch(directory_entry const& de, Callback cb, const codecvt_type* cvt, directory_entry_tag); + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(Source const& source, Callback cb, const codecvt_type* cvt) +{ + return path_traits::dispatch(source, cb, cvt, + typename path_traits::path_source_traits< typename boost::remove_cv< Source >::type >::tag_type()); +} + + +typedef char yes_type; +struct no_type { char buf[2]; }; + +#if !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +namespace is_convertible_to_path_source_impl { + +yes_type check(const char*); +yes_type check(const wchar_t*); +yes_type check(std::string const&); +yes_type check(std::wstring const&); +yes_type check(boost::container::basic_string< char, std::char_traits< char >, void > const&); +yes_type check(boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const&); +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +yes_type check(std::string_view const&); +yes_type check(std::wstring_view const&); +#endif +yes_type check(boost::basic_string_view< char, std::char_traits< char > > const&); +yes_type check(boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const&); +#if !defined(BOOST_NO_CXX11_NULLPTR) +no_type check(std::nullptr_t); +#endif +no_type check(...); + +} // namespace is_convertible_to_path_source_impl + +//! The type trait indicates whether the type has a conversion path to one of the path source types +template< typename T > +struct is_convertible_to_path_source : + public boost::integral_constant< + bool, + sizeof(is_convertible_to_path_source_impl::check(boost::declval< T const& >())) == sizeof(yes_type) + > +{ +}; + +#else // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +// Note: We use separate checks for convertibility to std::string_view and other types to avoid ambiguity with an implicit range constructor +// of std::string_view in the early C++23 draft (N4892). If a user's type is convertible to e.g. std::string and also satisfies +// ranges::contiguous_range and ranges::sized_range concepts then the conversion is ambiguous: the type is convertible to std::string +// through the conversion operator in the user's class and is also convertible to std::string_view through the implicit conversion +// constructor in std::string_view. The solution is to check convertibility to std::string_view separately first. + +namespace is_convertible_to_std_string_view_impl { + +yes_type check(std::string_view const&); +yes_type check(std::wstring_view const&); +#if !defined(BOOST_NO_CXX11_NULLPTR) +no_type check(std::nullptr_t); +#endif +no_type check(...); + +} // namespace is_convertible_to_std_string_view_impl + +template< typename T > +struct is_convertible_to_std_string_view : + public boost::integral_constant< + bool, + sizeof(is_convertible_to_std_string_view_impl::check(boost::declval< T const& >())) == sizeof(yes_type) + > +{ +}; + +namespace is_convertible_to_path_source_non_std_string_view_impl { + +yes_type check(const char*); +yes_type check(const wchar_t*); +yes_type check(std::string const&); +yes_type check(std::wstring const&); +yes_type check(boost::container::basic_string< char, std::char_traits< char >, void > const&); +yes_type check(boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const&); +yes_type check(boost::basic_string_view< char, std::char_traits< char > > const&); +yes_type check(boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const&); +#if !defined(BOOST_NO_CXX11_NULLPTR) +no_type check(std::nullptr_t); +#endif +no_type check(...); + +} // namespace is_convertible_to_path_source_non_std_string_view_impl + +template< typename T > +struct is_convertible_to_path_source_non_std_string_view : + public boost::integral_constant< + bool, + sizeof(is_convertible_to_path_source_non_std_string_view_impl::check(boost::declval< T const& >())) == sizeof(yes_type) + > +{ +}; + +//! The type trait indicates whether the type has a conversion path to one of the path source types +template< typename T > +struct is_convertible_to_path_source : + public boost::disjunction< + is_convertible_to_std_string_view< T >, + is_convertible_to_path_source_non_std_string_view< T > + >::type +{ +}; + +#endif // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +//! The type trait makes \a T dependent on the second template argument. Used to delay type resolution and name binding. +template< typename T, typename > +struct make_dependent +{ + typedef T type; +}; + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(const char* source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< const char*, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(const wchar_t* source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< const wchar_t*, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::string const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::string, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::wstring const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::wstring, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl +( + boost::container::basic_string< char, std::char_traits< char >, void > const& source, + Callback cb, + const codecvt_type* cvt +) +{ + typedef typename path_traits::make_dependent< boost::container::basic_string< char, std::char_traits< char >, void >, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl +( + boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void > const& source, + Callback cb, + const codecvt_type* cvt +) +{ + typedef typename path_traits::make_dependent< boost::container::basic_string< wchar_t, std::char_traits< wchar_t >, void >, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl +( + boost::basic_string_view< char, std::char_traits< char > > const& source, + Callback cb, + const codecvt_type* cvt +) +{ + typedef typename path_traits::make_dependent< boost::basic_string_view< char, std::char_traits< char > >, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl +( + boost::basic_string_view< wchar_t, std::char_traits< wchar_t > > const& source, + Callback cb, + const codecvt_type* cvt +) +{ + typedef typename path_traits::make_dependent< boost::basic_string_view< wchar_t, std::char_traits< wchar_t > >, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +#if !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::string_view const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::string_view, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_impl(std::wstring_view const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::wstring_view, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +#endif // !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL) +{ + typedef typename boost::remove_cv< Source >::type source_t; + return path_traits::dispatch_convertible_impl< source_t >(source, cb, cvt); +} + +#else // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_sv_impl(std::string_view const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::string_view, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_sv_impl(std::wstring_view const& source, Callback cb, const codecvt_type* cvt) +{ + typedef typename path_traits::make_dependent< std::wstring_view, Source >::type source_t; + return path_traits::dispatch(static_cast< source_t const& >(source), cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename boost::disable_if_c< + is_convertible_to_std_string_view< typename boost::remove_cv< Source >::type >::value, + typename Callback::result_type +>::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL) +{ + typedef typename boost::remove_cv< Source >::type source_t; + return path_traits::dispatch_convertible_impl< source_t >(source, cb, cvt); +} + +template< typename Source, typename Callback > +BOOST_FORCEINLINE typename boost::enable_if_c< + is_convertible_to_std_string_view< typename boost::remove_cv< Source >::type >::value, + typename Callback::result_type +>::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = NULL) +{ + typedef typename boost::remove_cv< Source >::type source_t; + return path_traits::dispatch_convertible_sv_impl< source_t >(source, cb, cvt); +} + +#endif // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) + +} // namespace path_traits +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_DETAIL_PATH_TRAITS_HPP diff --git a/boost/filesystem/detail/utf8_codecvt_facet.hpp b/boost/filesystem/detail/utf8_codecvt_facet.hpp new file mode 100644 index 0000000..4df9a7c --- /dev/null +++ b/boost/filesystem/detail/utf8_codecvt_facet.hpp @@ -0,0 +1,33 @@ +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). + +// Distributed under the Boost Software License, Version 1.0. +// (See http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP +#define BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP + +#include + +#include + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { \ + namespace filesystem { \ + namespace detail { + +#define BOOST_UTF8_END_NAMESPACE \ + } \ + } \ + } +#define BOOST_UTF8_DECL BOOST_FILESYSTEM_DECL + +#include + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + +#include + +#endif // BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP diff --git a/boost/filesystem/directory.hpp b/boost/filesystem/directory.hpp new file mode 100644 index 0000000..2afcfb6 --- /dev/null +++ b/boost/filesystem/directory.hpp @@ -0,0 +1,1113 @@ +// boost/filesystem/directory.hpp ---------------------------------------------------// + +// Copyright Beman Dawes 2002-2009 +// Copyright Jan Langer 2002 +// Copyright Dietmar Kuehl 2001 +// Copyright Vladimir Prus 2002 +// Copyright Andrey Semashev 2019, 2022 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_DIRECTORY_HPP +#define BOOST_FILESYSTEM_DIRECTORY_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include // must be the last #include + +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { + +class directory_iterator; + +namespace detail { + +struct directory_iterator_params; + +BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec); +BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec); + +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// directory_entry // +// // +//--------------------------------------------------------------------------------------// + +// GCC has a problem with a member function named path within a namespace or +// sub-namespace that also has a class named path. The workaround is to always +// fully qualify the name path when it refers to the class name. + +class directory_entry +{ + friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, detail::directory_iterator_params* params, system::error_code* ec); + friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec); + +public: + typedef boost::filesystem::path::value_type value_type; // enables class path ctor taking directory_entry + + directory_entry() BOOST_NOEXCEPT {} + + explicit directory_entry(boost::filesystem::path const& p); + +#if BOOST_FILESYSTEM_VERSION >= 4 + directory_entry(boost::filesystem::path const& p, system::error_code& ec) : + m_path(p) + { + refresh_impl(&ec); + if (ec) + m_path.clear(); + } +#else + directory_entry(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) : + m_path(p), m_status(st), m_symlink_status(symlink_st) + { + } +#endif + + directory_entry(directory_entry const& rhs) : + m_path(rhs.m_path), m_status(rhs.m_status), m_symlink_status(rhs.m_symlink_status) + { + } + + directory_entry& operator=(directory_entry const& rhs) + { + m_path = rhs.m_path; + m_status = rhs.m_status; + m_symlink_status = rhs.m_symlink_status; + return *this; + } + + // As of October 2015 the interaction between noexcept and =default is so troublesome + // for VC++, GCC, and probably other compilers, that =default is not used with noexcept + // functions. GCC is not even consistent for the same release on different platforms. + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + directory_entry(directory_entry&& rhs) BOOST_NOEXCEPT : + m_path(static_cast< boost::filesystem::path&& >(rhs.m_path)), + m_status(static_cast< file_status&& >(rhs.m_status)), + m_symlink_status(static_cast< file_status&& >(rhs.m_symlink_status)) + { + } + + directory_entry& operator=(directory_entry&& rhs) BOOST_NOEXCEPT + { + m_path = static_cast< boost::filesystem::path&& >(rhs.m_path); + m_status = static_cast< file_status&& >(rhs.m_status); + m_symlink_status = static_cast< file_status&& >(rhs.m_symlink_status); + return *this; + } + + void assign(boost::filesystem::path&& p); + +#if BOOST_FILESYSTEM_VERSION >= 4 + void assign(boost::filesystem::path&& p, system::error_code& ec) + { + m_path = static_cast< boost::filesystem::path&& >(p); + refresh_impl(&ec); + } +#else + void assign(boost::filesystem::path&& p, file_status st, file_status symlink_st = file_status()) + { + assign_with_status(static_cast< boost::filesystem::path&& >(p), st, symlink_st); + } +#endif +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + void assign(boost::filesystem::path const& p); + +#if BOOST_FILESYSTEM_VERSION >= 4 + void assign(boost::filesystem::path const& p, system::error_code& ec) + { + m_path = p; + refresh_impl(&ec); + } +#else + void assign(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) + { + assign_with_status(p, st, symlink_st); + } +#endif + + void replace_filename(boost::filesystem::path const& p); + +#if BOOST_FILESYSTEM_VERSION >= 4 + void replace_filename(boost::filesystem::path const& p, system::error_code& ec) + { + m_path.replace_filename(p); + refresh_impl(&ec); + } +#else + void replace_filename(boost::filesystem::path const& p, file_status st, file_status symlink_st = file_status()) + { + replace_filename_with_status(p, st, symlink_st); + } + + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_entry::replace_filename() instead") + void replace_leaf(boost::filesystem::path const& p, file_status st, file_status symlink_st) + { + replace_filename_with_status(p, st, symlink_st); + } +#endif + + boost::filesystem::path const& path() const BOOST_NOEXCEPT { return m_path; } + operator boost::filesystem::path const&() const BOOST_NOEXCEPT { return m_path; } + + void refresh() { refresh_impl(); } + void refresh(system::error_code& ec) BOOST_NOEXCEPT { refresh_impl(&ec); } + + file_status status() const + { + if (!filesystem::status_known(m_status)) + refresh_impl(); + return m_status; + } + + file_status status(system::error_code& ec) const BOOST_NOEXCEPT + { + if (!filesystem::status_known(m_status)) + refresh_impl(&ec); + return m_status; + } + + file_status symlink_status() const + { + if (!filesystem::status_known(m_symlink_status)) + refresh_impl(); + return m_symlink_status; + } + + file_status symlink_status(system::error_code& ec) const BOOST_NOEXCEPT + { + if (!filesystem::status_known(m_symlink_status)) + refresh_impl(&ec); + return m_symlink_status; + } + + filesystem::file_type file_type() const + { + if (!filesystem::type_present(m_status)) + refresh_impl(); + return m_status.type(); + } + + filesystem::file_type file_type(system::error_code& ec) const BOOST_NOEXCEPT + { + if (!filesystem::type_present(m_status)) + refresh_impl(&ec); + return m_status.type(); + } + + filesystem::file_type symlink_file_type() const + { + if (!filesystem::type_present(m_symlink_status)) + refresh_impl(); + return m_symlink_status.type(); + } + + filesystem::file_type symlink_file_type(system::error_code& ec) const BOOST_NOEXCEPT + { + if (!filesystem::type_present(m_symlink_status)) + refresh_impl(&ec); + return m_symlink_status.type(); + } + + bool exists() const + { + filesystem::file_type ft = this->file_type(); + return ft != filesystem::status_error && ft != filesystem::file_not_found; + } + + bool exists(system::error_code& ec) const BOOST_NOEXCEPT + { + filesystem::file_type ft = this->file_type(ec); + return ft != filesystem::status_error && ft != filesystem::file_not_found; + } + + bool is_regular_file() const + { + return this->file_type() == filesystem::regular_file; + } + + bool is_regular_file(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::regular_file; + } + + bool is_directory() const + { + return this->file_type() == filesystem::directory_file; + } + + bool is_directory(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::directory_file; + } + + bool is_symlink() const + { + return this->symlink_file_type() == filesystem::symlink_file; + } + + bool is_symlink(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->symlink_file_type(ec) == filesystem::symlink_file; + } + + bool is_block_file() const + { + return this->file_type() == filesystem::block_file; + } + + bool is_block_file(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::block_file; + } + + bool is_character_file() const + { + return this->file_type() == filesystem::character_file; + } + + bool is_character_file(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::character_file; + } + + bool is_fifo() const + { + return this->file_type() == filesystem::fifo_file; + } + + bool is_fifo(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::fifo_file; + } + + bool is_socket() const + { + return this->file_type() == filesystem::socket_file; + } + + bool is_socket(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->file_type(ec) == filesystem::socket_file; + } + + bool is_reparse_file() const + { + return this->symlink_file_type() == filesystem::reparse_file; + } + + bool is_reparse_file(system::error_code& ec) const BOOST_NOEXCEPT + { + return this->symlink_file_type(ec) == filesystem::reparse_file; + } + + bool is_other() const + { + filesystem::file_type ft = this->file_type(); + return ft != filesystem::status_error && ft != filesystem::file_not_found && + ft != filesystem::regular_file && ft != filesystem::directory_file; + } + + bool is_other(system::error_code& ec) const BOOST_NOEXCEPT + { + filesystem::file_type ft = this->file_type(ec); + return ft != filesystem::status_error && ft != filesystem::file_not_found && + ft != filesystem::regular_file && ft != filesystem::directory_file; + } + + bool operator==(directory_entry const& rhs) const { return m_path == rhs.m_path; } + bool operator!=(directory_entry const& rhs) const { return m_path != rhs.m_path; } + bool operator<(directory_entry const& rhs) const { return m_path < rhs.m_path; } + bool operator<=(directory_entry const& rhs) const { return m_path <= rhs.m_path; } + bool operator>(directory_entry const& rhs) const { return m_path > rhs.m_path; } + bool operator>=(directory_entry const& rhs) const { return m_path >= rhs.m_path; } + +private: + BOOST_FILESYSTEM_DECL void refresh_impl(system::error_code* ec = NULL) const; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + void assign_with_status(boost::filesystem::path&& p, file_status st, file_status symlink_st) + { + m_path = static_cast< boost::filesystem::path&& >(p); + m_status = static_cast< file_status&& >(st); + m_symlink_status = static_cast< file_status&& >(symlink_st); + } +#endif + + void assign_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st) + { + m_path = p; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + m_status = static_cast< file_status&& >(st); + m_symlink_status = static_cast< file_status&& >(symlink_st); +#else + m_status = st; + m_symlink_status = symlink_st; +#endif + } + + void replace_filename_with_status(boost::filesystem::path const& p, file_status st, file_status symlink_st) + { + m_path.replace_filename(p); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + m_status = static_cast< file_status&& >(st); + m_symlink_status = static_cast< file_status&& >(symlink_st); +#else + m_status = st; + m_symlink_status = symlink_st; +#endif + } + +private: + boost::filesystem::path m_path; + mutable file_status m_status; // stat()-like + mutable file_status m_symlink_status; // lstat()-like +}; + +#if !defined(BOOST_FILESYSTEM_SOURCE) + +inline directory_entry::directory_entry(boost::filesystem::path const& p) : + m_path(p) +{ +#if BOOST_FILESYSTEM_VERSION >= 4 + refresh_impl(); +#endif +} + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +inline void directory_entry::assign(boost::filesystem::path&& p) +{ + m_path = static_cast< boost::filesystem::path&& >(p); +#if BOOST_FILESYSTEM_VERSION >= 4 + refresh_impl(); +#else + m_status = file_status(); + m_symlink_status = file_status(); +#endif +} +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +inline void directory_entry::assign(boost::filesystem::path const& p) +{ + m_path = p; +#if BOOST_FILESYSTEM_VERSION >= 4 + refresh_impl(); +#else + m_status = file_status(); + m_symlink_status = file_status(); +#endif +} + +inline void directory_entry::replace_filename(boost::filesystem::path const& p) +{ + m_path.replace_filename(p); +#if BOOST_FILESYSTEM_VERSION >= 4 + refresh_impl(); +#else + m_status = file_status(); + m_symlink_status = file_status(); +#endif +} + +#endif // !defined(BOOST_FILESYSTEM_SOURCE) + +namespace detail { +namespace path_traits { + +// Dispatch function for integration with path class +template< typename Callback > +BOOST_FORCEINLINE typename Callback::result_type dispatch(directory_entry const& de, Callback cb, const codecvt_type* cvt, directory_entry_tag) +{ + boost::filesystem::path::string_type const& source = de.path().native(); + return cb(source.data(), source.data() + source.size(), cvt); +} + +} // namespace path_traits +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// directory_entry overloads // +// // +//--------------------------------------------------------------------------------------// + +// Without these functions, calling (for example) 'is_directory' with a 'directory_entry' results in: +// - a conversion to 'path' using 'operator boost::filesystem::path const&()', +// - then a call to 'is_directory(path const& p)' which recomputes the status with 'detail::status(p)'. +// +// These functions avoid a costly recomputation of the status if one calls 'is_directory(e)' instead of 'is_directory(e.status())' + +inline file_status status(directory_entry const& e) +{ + return e.status(); +} + +inline file_status status(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.status(ec); +} + +inline file_status symlink_status(directory_entry const& e) +{ + return e.symlink_status(); +} + +inline file_status symlink_status(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.symlink_status(ec); +} + +inline bool type_present(directory_entry const& e) +{ + return e.file_type() != filesystem::status_error; +} + +inline bool type_present(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.file_type(ec) != filesystem::status_error; +} + +inline bool status_known(directory_entry const& e) +{ + return filesystem::status_known(e.status()); +} + +inline bool status_known(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::status_known(e.status(ec)); +} + +inline bool exists(directory_entry const& e) +{ + return e.exists(); +} + +inline bool exists(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.exists(ec); +} + +inline bool is_regular_file(directory_entry const& e) +{ + return e.is_regular_file(); +} + +inline bool is_regular_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_regular_file(ec); +} + +inline bool is_directory(directory_entry const& e) +{ + return e.is_directory(); +} + +inline bool is_directory(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_directory(ec); +} + +inline bool is_symlink(directory_entry const& e) +{ + return e.is_symlink(); +} + +inline bool is_symlink(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_symlink(ec); +} + +inline bool is_block_file(directory_entry const& e) +{ + return e.is_block_file(); +} + +inline bool is_block_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_block_file(ec); +} + +inline bool is_character_file(directory_entry const& e) +{ + return e.is_character_file(); +} + +inline bool is_character_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_character_file(ec); +} + +inline bool is_fifo(directory_entry const& e) +{ + return e.is_fifo(); +} + +inline bool is_fifo(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_fifo(ec); +} + +inline bool is_socket(directory_entry const& e) +{ + return e.is_socket(); +} + +inline bool is_socket(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_socket(ec); +} + +inline bool is_reparse_file(directory_entry const& e) +{ + return e.is_reparse_file(); +} + +inline bool is_reparse_file(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_reparse_file(ec); +} + +inline bool is_other(directory_entry const& e) +{ + return e.is_other(); +} + +inline bool is_other(directory_entry const& e, system::error_code& ec) BOOST_NOEXCEPT +{ + return e.is_other(ec); +} + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead") +inline bool is_regular(directory_entry const& e) +{ + return filesystem::is_regular_file(e); +} +#endif + +//--------------------------------------------------------------------------------------// +// // +// directory_iterator helpers // +// // +//--------------------------------------------------------------------------------------// + +BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(directory_options, unsigned int) +{ + none = 0u, + skip_permission_denied = 1u, // if a directory cannot be opened because of insufficient permissions, pretend that the directory is empty + follow_directory_symlink = 1u << 1u, // recursive_directory_iterator: follow directory symlinks + skip_dangling_symlinks = 1u << 2u, // non-standard extension for recursive_directory_iterator: don't follow dangling directory symlinks, + pop_on_error = 1u << 3u, // non-standard extension for recursive_directory_iterator: instead of producing an end iterator on errors, + // repeatedly invoke pop() until it succeeds or the iterator becomes equal to end iterator + _detail_no_follow = 1u << 4u, // internal use only + _detail_no_push = 1u << 5u // internal use only +} +BOOST_SCOPED_ENUM_DECLARE_END(directory_options) + +BOOST_BITMASK(BOOST_SCOPED_ENUM_NATIVE(directory_options)) + +namespace detail { + +struct dir_itr_imp : + public boost::intrusive_ref_counter< dir_itr_imp > +{ +#ifdef BOOST_WINDOWS_API + bool close_handle; + unsigned char extra_data_format; + std::size_t current_offset; +#endif + directory_entry dir_entry; + void* handle; + + dir_itr_imp() BOOST_NOEXCEPT : +#ifdef BOOST_WINDOWS_API + close_handle(false), + extra_data_format(0u), + current_offset(0u), +#endif + handle(NULL) + { + } + BOOST_FILESYSTEM_DECL ~dir_itr_imp() BOOST_NOEXCEPT; + + BOOST_FILESYSTEM_DECL static void* operator new(std::size_t class_size, std::size_t extra_size) BOOST_NOEXCEPT; + BOOST_FILESYSTEM_DECL static void operator delete(void* p, std::size_t extra_size) BOOST_NOEXCEPT; + BOOST_FILESYSTEM_DECL static void operator delete(void* p) BOOST_NOEXCEPT; +}; + +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// directory_iterator // +// // +//--------------------------------------------------------------------------------------// + +class directory_iterator : + public boost::iterator_facade< + directory_iterator, + directory_entry, + boost::single_pass_traversal_tag + > +{ + friend class boost::iterator_core_access; + + friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, detail::directory_iterator_params* params, system::error_code* ec); + friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec); + +public: + directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator + + // iterator_facade derived classes don't seem to like implementations in + // separate translation unit dll's, so forward to detail functions + explicit directory_iterator(path const& p, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts = directory_options::none) + { + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), NULL, NULL); + } + + directory_iterator(path const& p, system::error_code& ec) BOOST_NOEXCEPT + { + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(directory_options::none), NULL, &ec); + } + + directory_iterator(path const& p, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts, system::error_code& ec) BOOST_NOEXCEPT + { + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), NULL, &ec); + } + + BOOST_DEFAULTED_FUNCTION(directory_iterator(directory_iterator const& that), : m_imp(that.m_imp) {}) + BOOST_DEFAULTED_FUNCTION(directory_iterator& operator=(directory_iterator const& that), { m_imp = that.m_imp; return *this; }) + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + directory_iterator(directory_iterator&& that) BOOST_NOEXCEPT : + m_imp(static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp)) + { + } + + directory_iterator& operator=(directory_iterator&& that) BOOST_NOEXCEPT + { + m_imp = static_cast< boost::intrusive_ptr< detail::dir_itr_imp >&& >(that.m_imp); + return *this; + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + directory_iterator& increment(system::error_code& ec) BOOST_NOEXCEPT + { + detail::directory_iterator_increment(*this, &ec); + return *this; + } + +private: + boost::iterator_facade< + directory_iterator, + directory_entry, + boost::single_pass_traversal_tag + >::reference dereference() const + { + BOOST_ASSERT_MSG(!is_end(), "attempt to dereference end directory iterator"); + return m_imp->dir_entry; + } + + void increment() { detail::directory_iterator_increment(*this, NULL); } + + bool equal(directory_iterator const& rhs) const BOOST_NOEXCEPT + { + return m_imp == rhs.m_imp || (is_end() && rhs.is_end()); + } + + bool is_end() const BOOST_NOEXCEPT + { + // Note: The check for handle is needed because the iterator can be copied and the copy + // can be incremented to end while the original iterator still refers to the same dir_itr_imp. + return !m_imp || !m_imp->handle; + } + +private: + // intrusive_ptr provides the shallow-copy semantics required for single pass iterators + // (i.e. InputIterators). The end iterator is indicated by is_end(). + boost::intrusive_ptr< detail::dir_itr_imp > m_imp; +}; + +// enable directory_iterator C++11 range-based for statement use --------------------// + +// begin() and end() are only used by a range-based for statement in the context of +// auto - thus the top-level const is stripped - so returning const is harmless and +// emphasizes begin() is just a pass through. +inline directory_iterator const& begin(directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline directory_iterator end(directory_iterator const&) BOOST_NOEXCEPT +{ + return directory_iterator(); +} + +// enable C++14 generic accessors for range const iterators +inline directory_iterator const& cbegin(directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline directory_iterator cend(directory_iterator const&) BOOST_NOEXCEPT +{ + return directory_iterator(); +} + +// enable directory_iterator BOOST_FOREACH -----------------------------------------// + +inline directory_iterator& range_begin(directory_iterator& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline directory_iterator range_begin(directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline directory_iterator range_end(directory_iterator&) BOOST_NOEXCEPT +{ + return directory_iterator(); +} + +inline directory_iterator range_end(directory_iterator const&) BOOST_NOEXCEPT +{ + return directory_iterator(); +} + +} // namespace filesystem + +// namespace boost template specializations +template< typename C, typename Enabler > +struct range_mutable_iterator; + +template<> +struct range_mutable_iterator< boost::filesystem::directory_iterator, void > +{ + typedef boost::filesystem::directory_iterator type; +}; + +template< typename C, typename Enabler > +struct range_const_iterator; + +template<> +struct range_const_iterator< boost::filesystem::directory_iterator, void > +{ + typedef boost::filesystem::directory_iterator type; +}; + +namespace filesystem { + +//--------------------------------------------------------------------------------------// +// // +// recursive_directory_iterator helpers // +// // +//--------------------------------------------------------------------------------------// + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +// Deprecated enum, use directory_options instead +BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(symlink_option, unsigned int) +{ + none = static_cast< unsigned int >(directory_options::none), + no_recurse = none, // don't follow directory symlinks (default behavior) + recurse = static_cast< unsigned int >(directory_options::follow_directory_symlink), // follow directory symlinks + _detail_no_push = static_cast< unsigned int >(directory_options::_detail_no_push) // internal use only +} +BOOST_SCOPED_ENUM_DECLARE_END(symlink_option) + +BOOST_BITMASK(BOOST_SCOPED_ENUM_NATIVE(symlink_option)) +#endif // BOOST_FILESYSTEM_NO_DEPRECATED + +class recursive_directory_iterator; + +namespace detail { + +struct recur_dir_itr_imp : + public boost::intrusive_ref_counter< recur_dir_itr_imp > +{ + typedef directory_iterator element_type; + std::vector< element_type > m_stack; + // directory_options values, declared as unsigned int for ABI compatibility + unsigned int m_options; + + explicit recur_dir_itr_imp(unsigned int opts) BOOST_NOEXCEPT : m_options(opts) {} +}; + +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, unsigned int opts, system::error_code* ec); +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec); + +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// recursive_directory_iterator // +// // +//--------------------------------------------------------------------------------------// + +class recursive_directory_iterator : + public boost::iterator_facade< + recursive_directory_iterator, + directory_entry, + boost::single_pass_traversal_tag + > +{ + friend class boost::iterator_core_access; + + friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, unsigned int opts, system::error_code* ec); + friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); + friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec); + +public: + recursive_directory_iterator() BOOST_NOEXCEPT {} // creates the "end" iterator + + explicit recursive_directory_iterator(path const& dir_path) + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(directory_options::none), NULL); + } + + recursive_directory_iterator(path const& dir_path, system::error_code& ec) + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(directory_options::none), &ec); + } + + recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts) + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), NULL); + } + + recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts, system::error_code& ec) + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), &ec); + } + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + // Deprecated constructors + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_options instead of symlink_option") + recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts) + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), NULL); + } + + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use directory_options instead of symlink_option") + recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts, system::error_code& ec) BOOST_NOEXCEPT + { + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), &ec); + } +#endif // BOOST_FILESYSTEM_NO_DEPRECATED + + BOOST_DEFAULTED_FUNCTION(recursive_directory_iterator(recursive_directory_iterator const& that), : m_imp(that.m_imp) {}) + BOOST_DEFAULTED_FUNCTION(recursive_directory_iterator& operator=(recursive_directory_iterator const& that), { m_imp = that.m_imp; return *this; }) + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + recursive_directory_iterator(recursive_directory_iterator&& that) BOOST_NOEXCEPT : + m_imp(static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp)) + { + } + + recursive_directory_iterator& operator=(recursive_directory_iterator&& that) BOOST_NOEXCEPT + { + m_imp = static_cast< boost::intrusive_ptr< detail::recur_dir_itr_imp >&& >(that.m_imp); + return *this; + } +#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + recursive_directory_iterator& increment(system::error_code& ec) BOOST_NOEXCEPT + { + detail::recursive_directory_iterator_increment(*this, &ec); + return *this; + } + + int depth() const BOOST_NOEXCEPT + { + BOOST_ASSERT_MSG(!is_end(), "depth() on end recursive_directory_iterator"); + return static_cast< int >(m_imp->m_stack.size() - 1u); + } + + bool recursion_pending() const BOOST_NOEXCEPT + { + BOOST_ASSERT_MSG(!is_end(), "recursion_pending() on end recursive_directory_iterator"); + return (m_imp->m_options & static_cast< unsigned int >(directory_options::_detail_no_push)) == 0u; + } + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator::depth() instead") + int level() const BOOST_NOEXCEPT + { + return depth(); + } + bool no_push_pending() const BOOST_NOEXCEPT { return !recursion_pending(); } + bool no_push_request() const BOOST_NOEXCEPT { return !recursion_pending(); } +#endif + + void pop() + { + detail::recursive_directory_iterator_pop(*this, NULL); + } + + void pop(system::error_code& ec) BOOST_NOEXCEPT + { + detail::recursive_directory_iterator_pop(*this, &ec); + } + + void disable_recursion_pending(bool value = true) BOOST_NOEXCEPT + { + BOOST_ASSERT_MSG(!is_end(), "disable_recursion_pending() on end recursive_directory_iterator"); + if (value) + m_imp->m_options |= static_cast< unsigned int >(directory_options::_detail_no_push); + else + m_imp->m_options &= ~static_cast< unsigned int >(directory_options::_detail_no_push); + } + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator::disable_recursion_pending() instead") + void no_push(bool value = true) BOOST_NOEXCEPT + { + disable_recursion_pending(value); + } +#endif + + file_status status() const + { + BOOST_ASSERT_MSG(!is_end(), "status() on end recursive_directory_iterator"); + return m_imp->m_stack.back()->status(); + } + + file_status symlink_status() const + { + BOOST_ASSERT_MSG(!is_end(), "symlink_status() on end recursive_directory_iterator"); + return m_imp->m_stack.back()->symlink_status(); + } + +private: + boost::iterator_facade< + recursive_directory_iterator, + directory_entry, + boost::single_pass_traversal_tag + >::reference dereference() const + { + BOOST_ASSERT_MSG(!is_end(), "dereference of end recursive_directory_iterator"); + return *m_imp->m_stack.back(); + } + + void increment() { detail::recursive_directory_iterator_increment(*this, NULL); } + + bool equal(recursive_directory_iterator const& rhs) const BOOST_NOEXCEPT + { + return m_imp == rhs.m_imp || (is_end() && rhs.is_end()); + } + + bool is_end() const BOOST_NOEXCEPT + { + // Note: The check for m_stack.empty() is needed because the iterator can be copied and the copy + // can be incremented to end while the original iterator still refers to the same recur_dir_itr_imp. + return !m_imp || m_imp->m_stack.empty(); + } + +private: + // intrusive_ptr provides the shallow-copy semantics required for single pass iterators + // (i.e. InputIterators). The end iterator is indicated by is_end(). + boost::intrusive_ptr< detail::recur_dir_itr_imp > m_imp; +}; + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use recursive_directory_iterator instead") +typedef recursive_directory_iterator wrecursive_directory_iterator; +#endif + +// enable recursive directory iterator C++11 range-base for statement use ----------// + +// begin() and end() are only used by a range-based for statement in the context of +// auto - thus the top-level const is stripped - so returning const is harmless and +// emphasizes begin() is just a pass through. +inline recursive_directory_iterator const& begin(recursive_directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline recursive_directory_iterator end(recursive_directory_iterator const&) BOOST_NOEXCEPT +{ + return recursive_directory_iterator(); +} + +// enable C++14 generic accessors for range const iterators +inline recursive_directory_iterator const& cbegin(recursive_directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline recursive_directory_iterator cend(recursive_directory_iterator const&) BOOST_NOEXCEPT +{ + return recursive_directory_iterator(); +} + +// enable recursive directory iterator BOOST_FOREACH -------------------------------// + +inline recursive_directory_iterator& range_begin(recursive_directory_iterator& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline recursive_directory_iterator range_begin(recursive_directory_iterator const& iter) BOOST_NOEXCEPT +{ + return iter; +} + +inline recursive_directory_iterator range_end(recursive_directory_iterator&) BOOST_NOEXCEPT +{ + return recursive_directory_iterator(); +} + +inline recursive_directory_iterator range_end(recursive_directory_iterator const&) BOOST_NOEXCEPT +{ + return recursive_directory_iterator(); +} + +} // namespace filesystem + +// namespace boost template specializations +template<> +struct range_mutable_iterator< boost::filesystem::recursive_directory_iterator, void > +{ + typedef boost::filesystem::recursive_directory_iterator type; +}; + +template<> +struct range_const_iterator< boost::filesystem::recursive_directory_iterator, void > +{ + typedef boost::filesystem::recursive_directory_iterator type; +}; + +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_DIRECTORY_HPP diff --git a/boost/filesystem/exception.hpp b/boost/filesystem/exception.hpp new file mode 100644 index 0000000..5980776 --- /dev/null +++ b/boost/filesystem/exception.hpp @@ -0,0 +1,92 @@ +// boost/filesystem/exception.hpp -----------------------------------------------------// + +// Copyright Beman Dawes 2003 +// Copyright Andrey Semashev 2019 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#ifndef BOOST_FILESYSTEM_EXCEPTION_HPP +#define BOOST_FILESYSTEM_EXCEPTION_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +//--------------------------------------------------------------------------------------// +// // +// class filesystem_error // +// // +//--------------------------------------------------------------------------------------// + +class BOOST_SYMBOL_VISIBLE filesystem_error : + public system::system_error +{ + // see http://www.boost.org/more/error_handling.html for design rationale + +public: + BOOST_FILESYSTEM_DECL filesystem_error(const char* what_arg, system::error_code ec); + BOOST_FILESYSTEM_DECL filesystem_error(std::string const& what_arg, system::error_code ec); + BOOST_FILESYSTEM_DECL filesystem_error(const char* what_arg, path const& path1_arg, system::error_code ec); + BOOST_FILESYSTEM_DECL filesystem_error(std::string const& what_arg, path const& path1_arg, system::error_code ec); + BOOST_FILESYSTEM_DECL filesystem_error(const char* what_arg, path const& path1_arg, path const& path2_arg, system::error_code ec); + BOOST_FILESYSTEM_DECL filesystem_error(std::string const& what_arg, path const& path1_arg, path const& path2_arg, system::error_code ec); + + BOOST_FILESYSTEM_DECL filesystem_error(filesystem_error const& that); + BOOST_FILESYSTEM_DECL filesystem_error& operator=(filesystem_error const& that); + + BOOST_FILESYSTEM_DECL ~filesystem_error() BOOST_NOEXCEPT_OR_NOTHROW; + + path const& path1() const BOOST_NOEXCEPT + { + return m_imp_ptr.get() ? m_imp_ptr->m_path1 : get_empty_path(); + } + path const& path2() const BOOST_NOEXCEPT + { + return m_imp_ptr.get() ? m_imp_ptr->m_path2 : get_empty_path(); + } + + BOOST_FILESYSTEM_DECL const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE; + +private: + BOOST_FILESYSTEM_DECL static path const& get_empty_path() BOOST_NOEXCEPT; + +private: + struct impl : + public boost::intrusive_ref_counter< impl > + { + path m_path1; // may be empty() + path m_path2; // may be empty() + std::string m_what; // not built until needed + + BOOST_DEFAULTED_FUNCTION(impl(), {}) + explicit impl(path const& path1) : + m_path1(path1) + { + } + impl(path const& path1, path const& path2) : + m_path1(path1), m_path2(path2) + { + } + }; + boost::intrusive_ptr< impl > m_imp_ptr; +}; + +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_EXCEPTION_HPP diff --git a/boost/filesystem/file_status.hpp b/boost/filesystem/file_status.hpp new file mode 100644 index 0000000..fb36240 --- /dev/null +++ b/boost/filesystem/file_status.hpp @@ -0,0 +1,269 @@ +// boost/filesystem/file_status.hpp --------------------------------------------------// + +// Copyright Beman Dawes 2002-2009 +// Copyright Jan Langer 2002 +// Copyright Dietmar Kuehl 2001 +// Copyright Vladimir Prus 2002 +// Copyright Andrey Semashev 2019 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_FILE_STATUS_HPP +#define BOOST_FILESYSTEM_FILE_STATUS_HPP + +#include +#include + +#include // must be the last #include + +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { + +//--------------------------------------------------------------------------------------// +// file_type // +//--------------------------------------------------------------------------------------// + +enum file_type +{ + status_error, +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED + status_unknown = status_error, +#endif + file_not_found, + regular_file, + directory_file, + // the following may not apply to some operating systems or file systems + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + reparse_file, // Windows: FILE_ATTRIBUTE_REPARSE_POINT that is not a symlink + type_unknown // file does exist, but isn't one of the above types or + // we don't have strong enough permission to find its type +}; + +//--------------------------------------------------------------------------------------// +// perms // +//--------------------------------------------------------------------------------------// + +enum perms +{ + no_perms = 0, // file_not_found is no_perms rather than perms_not_known + + // POSIX equivalent macros given in comments. + // Values are from POSIX and are given in octal per the POSIX standard. + + // permission bits + + owner_read = 0400, // S_IRUSR, Read permission, owner + owner_write = 0200, // S_IWUSR, Write permission, owner + owner_exe = 0100, // S_IXUSR, Execute/search permission, owner + owner_all = 0700, // S_IRWXU, Read, write, execute/search by owner + + group_read = 040, // S_IRGRP, Read permission, group + group_write = 020, // S_IWGRP, Write permission, group + group_exe = 010, // S_IXGRP, Execute/search permission, group + group_all = 070, // S_IRWXG, Read, write, execute/search by group + + others_read = 04, // S_IROTH, Read permission, others + others_write = 02, // S_IWOTH, Write permission, others + others_exe = 01, // S_IXOTH, Execute/search permission, others + others_all = 07, // S_IRWXO, Read, write, execute/search by others + + all_all = 0777, // owner_all|group_all|others_all + + // other POSIX bits + + set_uid_on_exe = 04000, // S_ISUID, Set-user-ID on execution + set_gid_on_exe = 02000, // S_ISGID, Set-group-ID on execution + sticky_bit = 01000, // S_ISVTX, + // (POSIX XSI) On directories, restricted deletion flag + // (V7) 'sticky bit': save swapped text even after use + // (SunOS) On non-directories: don't cache this file + // (SVID-v4.2) On directories: restricted deletion flag + // Also see http://en.wikipedia.org/wiki/Sticky_bit + + perms_mask = 07777, // all_all|set_uid_on_exe|set_gid_on_exe|sticky_bit + + perms_not_known = 0xFFFF, // present when directory_entry cache not loaded + + // options for permissions() function + + add_perms = 0x1000, // adds the given permission bits to the current bits + remove_perms = 0x2000, // removes the given permission bits from the current bits; + // choose add_perms or remove_perms, not both; if neither add_perms + // nor remove_perms is given, replace the current bits with + // the given bits. + + symlink_perms = 0x4000, // on POSIX, don't resolve symlinks; implied on Windows + + // BOOST_BITMASK op~ casts to int32_least_t, producing invalid enum values + _detail_extend_perms_32_1 = 0x7fffffff, + _detail_extend_perms_32_2 = -0x7fffffff - 1 +}; + +BOOST_BITMASK(perms) + +//--------------------------------------------------------------------------------------// +// file_status // +//--------------------------------------------------------------------------------------// + +class file_status +{ +public: + BOOST_CONSTEXPR file_status() BOOST_NOEXCEPT : + m_value(status_error), + m_perms(perms_not_known) + { + } + explicit BOOST_CONSTEXPR file_status(file_type v) BOOST_NOEXCEPT : + m_value(v), + m_perms(perms_not_known) + { + } + BOOST_CONSTEXPR file_status(file_type v, perms prms) BOOST_NOEXCEPT : + m_value(v), + m_perms(prms) + { + } + + // As of October 2015 the interaction between noexcept and =default is so troublesome + // for VC++, GCC, and probably other compilers, that =default is not used with noexcept + // functions. GCC is not even consistent for the same release on different platforms. + + BOOST_CONSTEXPR file_status(file_status const& rhs) BOOST_NOEXCEPT : + m_value(rhs.m_value), + m_perms(rhs.m_perms) + { + } + BOOST_CXX14_CONSTEXPR file_status& operator=(file_status const& rhs) BOOST_NOEXCEPT + { + m_value = rhs.m_value; + m_perms = rhs.m_perms; + return *this; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + // Note: std::move is not constexpr in C++11, that's why we're not using it here + BOOST_CONSTEXPR file_status(file_status&& rhs) BOOST_NOEXCEPT : + m_value(static_cast< file_type&& >(rhs.m_value)), + m_perms(static_cast< perms&& >(rhs.m_perms)) + { + } + BOOST_CXX14_CONSTEXPR file_status& operator=(file_status&& rhs) BOOST_NOEXCEPT + { + m_value = static_cast< file_type&& >(rhs.m_value); + m_perms = static_cast< perms&& >(rhs.m_perms); + return *this; + } +#endif + + // observers + BOOST_CONSTEXPR file_type type() const BOOST_NOEXCEPT { return m_value; } + BOOST_CONSTEXPR perms permissions() const BOOST_NOEXCEPT { return m_perms; } + + // modifiers + BOOST_CXX14_CONSTEXPR void type(file_type v) BOOST_NOEXCEPT { m_value = v; } + BOOST_CXX14_CONSTEXPR void permissions(perms prms) BOOST_NOEXCEPT { m_perms = prms; } + + BOOST_CONSTEXPR bool operator==(file_status const& rhs) const BOOST_NOEXCEPT + { + return type() == rhs.type() && permissions() == rhs.permissions(); + } + BOOST_CONSTEXPR bool operator!=(file_status const& rhs) const BOOST_NOEXCEPT + { + return !(*this == rhs); + } + +private: + file_type m_value; + perms m_perms; +}; + +inline BOOST_CONSTEXPR bool type_present(file_status f) BOOST_NOEXCEPT +{ + return f.type() != filesystem::status_error; +} + +inline BOOST_CONSTEXPR bool permissions_present(file_status f) BOOST_NOEXCEPT +{ + return f.permissions() != filesystem::perms_not_known; +} + +inline BOOST_CONSTEXPR bool status_known(file_status f) BOOST_NOEXCEPT +{ + return filesystem::type_present(f) && filesystem::permissions_present(f); +} + +inline BOOST_CONSTEXPR bool exists(file_status f) BOOST_NOEXCEPT +{ + return f.type() != filesystem::status_error && f.type() != filesystem::file_not_found; +} + +inline BOOST_CONSTEXPR bool is_regular_file(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::regular_file; +} + +inline BOOST_CONSTEXPR bool is_directory(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::directory_file; +} + +inline BOOST_CONSTEXPR bool is_symlink(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::symlink_file; +} + +inline BOOST_CONSTEXPR bool is_block_file(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::block_file; +} + +inline BOOST_CONSTEXPR bool is_character_file(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::character_file; +} + +inline BOOST_CONSTEXPR bool is_fifo(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::fifo_file; +} + +inline BOOST_CONSTEXPR bool is_socket(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::socket_file; +} + +inline BOOST_CONSTEXPR bool is_reparse_file(file_status f) BOOST_NOEXCEPT +{ + return f.type() == filesystem::reparse_file; +} + +inline BOOST_CONSTEXPR bool is_other(file_status f) BOOST_NOEXCEPT +{ + return filesystem::exists(f) && !filesystem::is_regular_file(f) && !filesystem::is_directory(f) && !filesystem::is_symlink(f); +} + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead") +inline bool is_regular(file_status f) BOOST_NOEXCEPT +{ + return filesystem::is_regular_file(f); +} +#endif + +} // namespace filesystem +} // namespace boost + +#include // pops abi_prefix.hpp pragmas + +#endif // BOOST_FILESYSTEM_FILE_STATUS_HPP diff --git a/boost/filesystem/fstream.hpp b/boost/filesystem/fstream.hpp new file mode 100644 index 0000000..3343651 --- /dev/null +++ b/boost/filesystem/fstream.hpp @@ -0,0 +1,269 @@ +// boost/filesystem/fstream.hpp ------------------------------------------------------// + +// Copyright Beman Dawes 2002 +// Copyright Andrey Semashev 2021-2023 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_FSTREAM_HPP +#define BOOST_FILESYSTEM_FSTREAM_HPP + +#include +#include +#include +#include +#include + +#include // must be the last #include + +#if defined(BOOST_WINDOWS_API) +// On Windows, except for standard libaries known to have wchar_t overloads for +// file stream I/O, use path::string() to get a narrow character c_str() +#if (defined(_CPPLIB_VER) && _CPPLIB_VER >= 405 && !defined(_STLPORT_VERSION)) || \ + (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 7000 && defined(_LIBCPP_HAS_OPEN_WITH_WCHAR)) +// Use wide characters directly +// Note: We don't use C++17 std::filesystem::path as a means to pass wide paths +// to file streams because of various problems: +// - std::filesystem is available in gcc 8 but it is broken there (fails to compile path definition +// on Windows). Compilation errors seem to be fixed since gcc 9. +// - In gcc 10.2 and clang 8.0.1 on Cygwin64, the path attempts to convert the wide string to narrow +// and fails in runtime. This may be system locale dependent, and performing character code conversion +// is against the purpose of using std::filesystem::path anyway. +// - Other std::filesystem implementations were not tested, so it is not known if they actually work +// with wide paths. +#define BOOST_FILESYSTEM_C_STR(p) p.c_str() +#else +// Use narrow characters, since wide not available +#define BOOST_FILESYSTEM_C_STR(p) p.string().c_str() +#endif +#endif // defined(BOOST_WINDOWS_API) + +#if !defined(BOOST_FILESYSTEM_C_STR) +#define BOOST_FILESYSTEM_C_STR(p) p.c_str() +#endif + +#if defined(BOOST_MSVC) +#pragma warning(push) +// 'boost::filesystem::basic_fstream' : inherits 'std::basic_istream<_Elem,_Traits>::std::basic_istream<_Elem,_Traits>::_Add_vtordisp1' via dominance +#pragma warning(disable : 4250) +#endif + +namespace boost { +namespace filesystem { + +//--------------------------------------------------------------------------------------// +// basic_filebuf // +//--------------------------------------------------------------------------------------// + +template< class Char, class Traits = std::char_traits< Char > > +class basic_filebuf : + public std::basic_filebuf< Char, Traits > +{ +private: + typedef std::basic_filebuf< Char, Traits > base_type; + +public: + BOOST_DEFAULTED_FUNCTION(basic_filebuf(), {}) + +#if !defined(BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS) +#if !defined(BOOST_NO_CXX11_DEFAULTED_MOVES) + basic_filebuf(basic_filebuf&&) = default; + basic_filebuf& operator= (basic_filebuf&&) = default; +#else + basic_filebuf(basic_filebuf&& that) : + base_type(static_cast< base_type&& >(that)) {} + + basic_filebuf& operator= (basic_filebuf&& that) + { + *static_cast< base_type* >(this) = static_cast< base_type&& >(that); + return *this; + } +#endif +#endif // !defined(BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS) + + BOOST_DELETED_FUNCTION(basic_filebuf(basic_filebuf const&)) + BOOST_DELETED_FUNCTION(basic_filebuf const& operator= (basic_filebuf const&)) + +public: + basic_filebuf* open(path const& p, std::ios_base::openmode mode) + { + return base_type::open(BOOST_FILESYSTEM_C_STR(p), mode) ? this : NULL; + } +}; + +//--------------------------------------------------------------------------------------// +// basic_ifstream // +//--------------------------------------------------------------------------------------// + +template< class Char, class Traits = std::char_traits< Char > > +class basic_ifstream : + public std::basic_ifstream< Char, Traits > +{ +private: + typedef std::basic_ifstream< Char, Traits > base_type; + +public: + BOOST_DEFAULTED_FUNCTION(basic_ifstream(), {}) + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + + explicit basic_ifstream(path const& p) : + base_type(BOOST_FILESYSTEM_C_STR(p), std::ios_base::in) {} + + basic_ifstream(path const& p, std::ios_base::openmode mode) : + base_type(BOOST_FILESYSTEM_C_STR(p), mode) {} + +#if !defined(BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS) + basic_ifstream(basic_ifstream&& that) : + base_type(static_cast< base_type&& >(that)) {} + + basic_ifstream& operator= (basic_ifstream&& that) + { + *static_cast< base_type* >(this) = static_cast< base_type&& >(that); + return *this; + } +#endif + + BOOST_DELETED_FUNCTION(basic_ifstream(basic_ifstream const&)) + BOOST_DELETED_FUNCTION(basic_ifstream const& operator= (basic_ifstream const&)) + +public: + void open(path const& p) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), std::ios_base::in); + } + + void open(path const& p, std::ios_base::openmode mode) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), mode); + } +}; + +//--------------------------------------------------------------------------------------// +// basic_ofstream // +//--------------------------------------------------------------------------------------// + +template< class Char, class Traits = std::char_traits< Char > > +class basic_ofstream : + public std::basic_ofstream< Char, Traits > +{ +private: + typedef std::basic_ofstream< Char, Traits > base_type; + +public: + BOOST_DEFAULTED_FUNCTION(basic_ofstream(), {}) + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + + explicit basic_ofstream(path const& p) : + base_type(BOOST_FILESYSTEM_C_STR(p), std::ios_base::out) {} + + basic_ofstream(path const& p, std::ios_base::openmode mode) : + base_type(BOOST_FILESYSTEM_C_STR(p), mode) {} + +#if !defined(BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS) + basic_ofstream(basic_ofstream&& that) : + base_type(static_cast< base_type&& >(that)) {} + + basic_ofstream& operator= (basic_ofstream&& that) + { + *static_cast< base_type* >(this) = static_cast< base_type&& >(that); + return *this; + } +#endif + + BOOST_DELETED_FUNCTION(basic_ofstream(basic_ofstream const&)) + BOOST_DELETED_FUNCTION(basic_ofstream const& operator= (basic_ofstream const&)) + +public: + void open(path const& p) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), std::ios_base::out); + } + + void open(path const& p, std::ios_base::openmode mode) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), mode); + } +}; + +//--------------------------------------------------------------------------------------// +// basic_fstream // +//--------------------------------------------------------------------------------------// + +template< class Char, class Traits = std::char_traits< Char > > +class basic_fstream : + public std::basic_fstream< Char, Traits > +{ +private: + typedef std::basic_fstream< Char, Traits > base_type; + +public: + BOOST_DEFAULTED_FUNCTION(basic_fstream(), {}) + + // use two signatures, rather than one signature with default second + // argument, to workaround VC++ 7.1 bug (ID VSWhidbey 38416) + + explicit basic_fstream(path const& p) : + base_type(BOOST_FILESYSTEM_C_STR(p), std::ios_base::in | std::ios_base::out) {} + + basic_fstream(path const& p, std::ios_base::openmode mode) : + base_type(BOOST_FILESYSTEM_C_STR(p), mode) {} + +#if !defined(BOOST_FILESYSTEM_DETAIL_NO_CXX11_MOVABLE_FSTREAMS) + basic_fstream(basic_fstream&& that) : + base_type(static_cast< base_type&& >(that)) {} + + basic_fstream& operator= (basic_fstream&& that) + { + *static_cast< base_type* >(this) = static_cast< base_type&& >(that); + return *this; + } +#endif + + BOOST_DELETED_FUNCTION(basic_fstream(basic_fstream const&)) + BOOST_DELETED_FUNCTION(basic_fstream const& operator= (basic_fstream const&)) + +public: + void open(path const& p) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), std::ios_base::in | std::ios_base::out); + } + + void open(path const& p, std::ios_base::openmode mode) + { + base_type::open(BOOST_FILESYSTEM_C_STR(p), mode); + } +}; + +//--------------------------------------------------------------------------------------// +// typedefs // +//--------------------------------------------------------------------------------------// + +typedef basic_filebuf< char > filebuf; +typedef basic_ifstream< char > ifstream; +typedef basic_ofstream< char > ofstream; +typedef basic_fstream< char > fstream; + +typedef basic_filebuf< wchar_t > wfilebuf; +typedef basic_ifstream< wchar_t > wifstream; +typedef basic_ofstream< wchar_t > wofstream; +typedef basic_fstream< wchar_t > wfstream; + +} // namespace filesystem +} // namespace boost + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#include + +#endif // BOOST_FILESYSTEM_FSTREAM_HPP diff --git a/boost/filesystem/operations.hpp b/boost/filesystem/operations.hpp new file mode 100644 index 0000000..0b7f736 --- /dev/null +++ b/boost/filesystem/operations.hpp @@ -0,0 +1,779 @@ +// boost/filesystem/operations.hpp ---------------------------------------------------// + +// Copyright Beman Dawes 2002-2009 +// Copyright Jan Langer 2002 +// Copyright Dietmar Kuehl 2001 +// Copyright Vladimir Prus 2002 +// Copyright Andrey Semashev 2020-2021 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_OPERATIONS_HPP +#define BOOST_FILESYSTEM_OPERATIONS_HPP + +#include +#include +#include + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +// These includes are left for backward compatibility and should be included directly by users, as needed +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include // must be the last #include + +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { + +struct space_info +{ + // all values are byte counts + boost::uintmax_t capacity; + boost::uintmax_t free; // <= capacity + boost::uintmax_t available; // <= free +}; + +BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(copy_options, unsigned int) +{ + none = 0u, // Default. For copy_file: error if the target file exists. For copy: do not recurse, follow symlinks, copy file contents. + + // copy_file options: + skip_existing = 1u, // Don't overwrite the existing target file, don't report an error + overwrite_existing = 1u << 1, // Overwrite existing file + update_existing = 1u << 2, // Overwrite existing file if its last write time is older than the replacement file + synchronize_data = 1u << 3, // Flush all buffered data written to the target file to permanent storage + synchronize = 1u << 4, // Flush all buffered data and attributes written to the target file to permanent storage + + // copy options: + recursive = 1u << 8, // Recurse into sub-directories + copy_symlinks = 1u << 9, // Copy symlinks as symlinks instead of copying the referenced file + skip_symlinks = 1u << 10, // Don't copy symlinks + directories_only = 1u << 11, // Only copy directory structure, do not copy non-directory files + create_symlinks = 1u << 12, // Create symlinks instead of copying files + create_hard_links = 1u << 13, // Create hard links instead of copying files + _detail_recursing = 1u << 14 // Internal use only, do not use +} +BOOST_SCOPED_ENUM_DECLARE_END(copy_options) + +BOOST_BITMASK(BOOST_SCOPED_ENUM_NATIVE(copy_options)) + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +BOOST_SCOPED_ENUM_DECLARE_BEGIN(copy_option) +{ + none = static_cast< unsigned int >(copy_options::none), + fail_if_exists = none, + overwrite_if_exists = static_cast< unsigned int >(copy_options::overwrite_existing) +} +BOOST_SCOPED_ENUM_DECLARE_END(copy_option) +#endif + +//--------------------------------------------------------------------------------------// +// implementation details // +//--------------------------------------------------------------------------------------// + +namespace detail { + +BOOST_FILESYSTEM_DECL +path absolute(path const& p, path const& base, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +file_status status(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +file_status symlink_status(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +bool is_empty(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path initial_path(system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path canonical(path const& p, path const& base, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void copy(path const& from, path const& to, unsigned int options, system::error_code* ec = NULL); +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +BOOST_FILESYSTEM_DECL +void copy_directory(path const& from, path const& to, system::error_code* ec = NULL); +#endif +BOOST_FILESYSTEM_DECL +bool copy_file(path const& from, path const& to, // See ticket #2925 + unsigned int options, system::error_code* ec = NULL); // see copy_options for options +BOOST_FILESYSTEM_DECL +void copy_symlink(path const& existing_symlink, path const& new_symlink, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +bool create_directories(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +bool create_directory(path const& p, const path* existing, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void create_directory_symlink(path const& to, path const& from, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void create_hard_link(path const& to, path const& from, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void create_symlink(path const& to, path const& from, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path current_path(system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void current_path(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +bool equivalent(path const& p1, path const& p2, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +boost::uintmax_t file_size(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +boost::uintmax_t hard_link_count(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +std::time_t creation_time(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +std::time_t last_write_time(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void last_write_time(path const& p, const std::time_t new_time, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void permissions(path const& p, perms prms, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path read_symlink(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path relative(path const& p, path const& base, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +bool remove(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +boost::uintmax_t remove_all(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void rename(path const& old_p, path const& new_p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +void resize_file(path const& p, uintmax_t size, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +space_info space(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path system_complete(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path temp_directory_path(system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path unique_path(path const& p, system::error_code* ec = NULL); +BOOST_FILESYSTEM_DECL +path weakly_canonical(path const& p, path const& base, system::error_code* ec = NULL); + +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// status query functions // +// // +//--------------------------------------------------------------------------------------// + +inline file_status status(path const& p) +{ + return detail::status(p); +} + +inline file_status status(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::status(p, &ec); +} + +inline file_status symlink_status(path const& p) +{ + return detail::symlink_status(p); +} + +inline file_status symlink_status(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::symlink_status(p, &ec); +} + +inline bool exists(path const& p) +{ + return filesystem::exists(detail::status(p)); +} + +inline bool exists(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::exists(detail::status(p, &ec)); +} + +inline bool is_regular_file(path const& p) +{ + return filesystem::is_regular_file(detail::status(p)); +} + +inline bool is_regular_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_regular_file(detail::status(p, &ec)); +} + +inline bool is_directory(path const& p) +{ + return filesystem::is_directory(detail::status(p)); +} + +inline bool is_directory(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_directory(detail::status(p, &ec)); +} + +inline bool is_symlink(path const& p) +{ + return filesystem::is_symlink(detail::symlink_status(p)); +} + +inline bool is_symlink(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_symlink(detail::symlink_status(p, &ec)); +} + +inline bool is_block_file(path const& p) +{ + return filesystem::is_block_file(detail::status(p)); +} + +inline bool is_block_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_block_file(detail::status(p, &ec)); +} + +inline bool is_character_file(path const& p) +{ + return filesystem::is_character_file(detail::status(p)); +} + +inline bool is_character_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_character_file(detail::status(p, &ec)); +} + +inline bool is_fifo(path const& p) +{ + return filesystem::is_fifo(detail::status(p)); +} + +inline bool is_fifo(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_fifo(detail::status(p, &ec)); +} + +inline bool is_socket(path const& p) +{ + return filesystem::is_socket(detail::status(p)); +} + +inline bool is_socket(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_socket(detail::status(p, &ec)); +} + +inline bool is_reparse_file(path const& p) +{ + return filesystem::is_reparse_file(detail::symlink_status(p)); +} + +inline bool is_reparse_file(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_reparse_file(detail::symlink_status(p, &ec)); +} + +inline bool is_other(path const& p) +{ + return filesystem::is_other(detail::status(p)); +} + +inline bool is_other(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_other(detail::status(p, &ec)); +} + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead") +inline bool is_regular(path const& p) +{ + return filesystem::is_regular_file(p); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_regular_file() instead") +inline bool is_regular(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return filesystem::is_regular_file(p, ec); +} +#endif + +inline bool is_empty(path const& p) +{ + return detail::is_empty(p); +} + +inline bool is_empty(path const& p, system::error_code& ec) +{ + return detail::is_empty(p, &ec); +} + +//--------------------------------------------------------------------------------------// +// // +// operational functions // +// // +//--------------------------------------------------------------------------------------// + +inline path initial_path() +{ + return detail::initial_path(); +} + +inline path initial_path(system::error_code& ec) +{ + return detail::initial_path(&ec); +} + +template< class Path > +path initial_path() +{ + return initial_path(); +} +template< class Path > +path initial_path(system::error_code& ec) +{ + return detail::initial_path(&ec); +} + +inline path current_path() +{ + return detail::current_path(); +} + +inline path current_path(system::error_code& ec) +{ + return detail::current_path(&ec); +} + +inline void current_path(path const& p) +{ + detail::current_path(p); +} + +inline void current_path(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::current_path(p, &ec); +} + +inline path absolute(path const& p, path const& base = current_path()) +{ + return detail::absolute(p, base); +} + +inline path absolute(path const& p, system::error_code& ec) +{ + path base = current_path(ec); + if (ec) + return path(); + return detail::absolute(p, base, &ec); +} + +inline path absolute(path const& p, path const& base, system::error_code& ec) +{ + return detail::absolute(p, base, &ec); +} + +inline path canonical(path const& p, path const& base = current_path()) +{ + return detail::canonical(p, base); +} + +inline path canonical(path const& p, system::error_code& ec) +{ + path base = current_path(ec); + if (ec) + return path(); + return detail::canonical(p, base, &ec); +} + +inline path canonical(path const& p, path const& base, system::error_code& ec) +{ + return detail::canonical(p, base, &ec); +} + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use absolute() instead") +inline path complete(path const& p) +{ + return absolute(p, initial_path()); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use absolute() instead") +inline path complete(path const& p, path const& base) +{ + return absolute(p, base); +} +#endif + +inline void copy(path const& from, path const& to) +{ + detail::copy(from, to, static_cast< unsigned int >(copy_options::none)); +} + +inline void copy(path const& from, path const& to, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::copy(from, to, static_cast< unsigned int >(copy_options::none), &ec); +} + +inline void copy(path const& from, path const& to, BOOST_SCOPED_ENUM_NATIVE(copy_options) options) +{ + detail::copy(from, to, static_cast< unsigned int >(options)); +} + +inline void copy(path const& from, path const& to, BOOST_SCOPED_ENUM_NATIVE(copy_options) options, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::copy(from, to, static_cast< unsigned int >(options), &ec); +} + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use create_directory() instead") +inline void copy_directory(path const& from, path const& to) +{ + detail::copy_directory(from, to); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use create_directory() instead") +inline void copy_directory(path const& from, path const& to, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::copy_directory(from, to, &ec); +} +#endif + +inline bool copy_file(path const& from, path const& to) +{ + return detail::copy_file(from, to, static_cast< unsigned int >(copy_options::none)); +} + +inline bool copy_file(path const& from, path const& to, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::copy_file(from, to, static_cast< unsigned int >(copy_options::none), &ec); +} + +inline bool copy_file(path const& from, path const& to, // See ticket #2925 + BOOST_SCOPED_ENUM_NATIVE(copy_options) options) +{ + return detail::copy_file(from, to, static_cast< unsigned int >(options)); +} + +inline bool copy_file(path const& from, path const& to, // See ticket #2925 + BOOST_SCOPED_ENUM_NATIVE(copy_options) options, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::copy_file(from, to, static_cast< unsigned int >(options), &ec); +} + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use copy_options instead of copy_option") +inline bool copy_file(path const& from, path const& to, // See ticket #2925 + BOOST_SCOPED_ENUM_NATIVE(copy_option) options) +{ + return detail::copy_file(from, to, static_cast< unsigned int >(options)); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use copy_options instead of copy_option") +inline bool copy_file(path const& from, path const& to, // See ticket #2925 + BOOST_SCOPED_ENUM_NATIVE(copy_option) options, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::copy_file(from, to, static_cast< unsigned int >(options), &ec); +} +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + +inline void copy_symlink(path const& existing_symlink, path const& new_symlink) +{ + detail::copy_symlink(existing_symlink, new_symlink); +} + +inline void copy_symlink(path const& existing_symlink, path const& new_symlink, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::copy_symlink(existing_symlink, new_symlink, &ec); +} + +inline bool create_directories(path const& p) +{ + return detail::create_directories(p); +} + +inline bool create_directories(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::create_directories(p, &ec); +} + +inline bool create_directory(path const& p) +{ + return detail::create_directory(p, NULL); +} + +inline bool create_directory(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::create_directory(p, NULL, &ec); +} + +inline bool create_directory(path const& p, path const& existing) +{ + return detail::create_directory(p, &existing); +} + +inline bool create_directory(path const& p, path const& existing, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::create_directory(p, &existing, &ec); +} + +inline void create_directory_symlink(path const& to, path const& from) +{ + detail::create_directory_symlink(to, from); +} + +inline void create_directory_symlink(path const& to, path const& from, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::create_directory_symlink(to, from, &ec); +} + +inline void create_hard_link(path const& to, path const& new_hard_link) +{ + detail::create_hard_link(to, new_hard_link); +} + +inline void create_hard_link(path const& to, path const& new_hard_link, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::create_hard_link(to, new_hard_link, &ec); +} + +inline void create_symlink(path const& to, path const& new_symlink) +{ + detail::create_symlink(to, new_symlink); +} + +inline void create_symlink(path const& to, path const& new_symlink, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::create_symlink(to, new_symlink, &ec); +} + +inline bool equivalent(path const& p1, path const& p2) +{ + return detail::equivalent(p1, p2); +} + +inline bool equivalent(path const& p1, path const& p2, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::equivalent(p1, p2, &ec); +} + +inline boost::uintmax_t file_size(path const& p) +{ + return detail::file_size(p); +} + +inline boost::uintmax_t file_size(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::file_size(p, &ec); +} + +inline boost::uintmax_t hard_link_count(path const& p) +{ + return detail::hard_link_count(p); +} + +inline boost::uintmax_t hard_link_count(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::hard_link_count(p, &ec); +} + +inline std::time_t creation_time(path const& p) +{ + return detail::creation_time(p); +} + +inline std::time_t creation_time(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::creation_time(p, &ec); +} + +inline std::time_t last_write_time(path const& p) +{ + return detail::last_write_time(p); +} + +inline std::time_t last_write_time(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::last_write_time(p, &ec); +} + +inline void last_write_time(path const& p, const std::time_t new_time) +{ + detail::last_write_time(p, new_time); +} + +inline void last_write_time(path const& p, const std::time_t new_time, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::last_write_time(p, new_time, &ec); +} + +inline void permissions(path const& p, perms prms) +{ + detail::permissions(p, prms); +} + +inline void permissions(path const& p, perms prms, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::permissions(p, prms, &ec); +} + +inline path read_symlink(path const& p) +{ + return detail::read_symlink(p); +} + +inline path read_symlink(path const& p, system::error_code& ec) +{ + return detail::read_symlink(p, &ec); +} + +inline bool remove(path const& p) +{ + return detail::remove(p); +} + +inline bool remove(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::remove(p, &ec); +} + +inline boost::uintmax_t remove_all(path const& p) +{ + return detail::remove_all(p); +} + +inline boost::uintmax_t remove_all(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::remove_all(p, &ec); +} + +inline void rename(path const& old_p, path const& new_p) +{ + detail::rename(old_p, new_p); +} + +inline void rename(path const& old_p, path const& new_p, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::rename(old_p, new_p, &ec); +} + +// name suggested by Scott McMurray +inline void resize_file(path const& p, uintmax_t size) +{ + detail::resize_file(p, size); +} + +inline void resize_file(path const& p, uintmax_t size, system::error_code& ec) BOOST_NOEXCEPT +{ + detail::resize_file(p, size, &ec); +} + +inline path relative(path const& p, path const& base = current_path()) +{ + return detail::relative(p, base); +} + +inline path relative(path const& p, system::error_code& ec) +{ + path base = current_path(ec); + if (ec) + return path(); + return detail::relative(p, base, &ec); +} + +inline path relative(path const& p, path const& base, system::error_code& ec) +{ + return detail::relative(p, base, &ec); +} + +inline space_info space(path const& p) +{ + return detail::space(p); +} + +inline space_info space(path const& p, system::error_code& ec) BOOST_NOEXCEPT +{ + return detail::space(p, &ec); +} + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use is_symlink(symlink_status(path)) instead") +inline bool symbolic_link_exists(path const& p) +{ + return is_symlink(filesystem::symlink_status(p)); +} +#endif + +inline path system_complete(path const& p) +{ + return detail::system_complete(p); +} + +inline path system_complete(path const& p, system::error_code& ec) +{ + return detail::system_complete(p, &ec); +} + +inline path temp_directory_path() +{ + return detail::temp_directory_path(); +} + +inline path temp_directory_path(system::error_code& ec) +{ + return detail::temp_directory_path(&ec); +} + +inline path unique_path(path const& p = "%%%%-%%%%-%%%%-%%%%") +{ + return detail::unique_path(p); +} + +inline path unique_path(path const& p, system::error_code& ec) +{ + return detail::unique_path(p, &ec); +} + +inline path weakly_canonical(path const& p, path const& base = current_path()) +{ + return detail::weakly_canonical(p, base); +} + +inline path weakly_canonical(path const& p, system::error_code& ec) +{ + path base = current_path(ec); + if (ec) + return path(); + return detail::weakly_canonical(p, base, &ec); +} + +inline path weakly_canonical(path const& p, path const& base, system::error_code& ec) +{ + return detail::weakly_canonical(p, base, &ec); +} + +// test helper -----------------------------------------------------------------------// + +// Not part of the documented interface since false positives are possible; +// there is no law that says that an OS that has large stat.st_size +// actually supports large file sizes. + +namespace detail { + +BOOST_FILESYSTEM_DECL bool possible_large_file_size_support(); + +} // namespace detail + +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_OPERATIONS_HPP diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp new file mode 100644 index 0000000..729e188 --- /dev/null +++ b/boost/filesystem/path.hpp @@ -0,0 +1,1836 @@ +// filesystem path.hpp ---------------------------------------------------------------// + +// Copyright Vladimir Prus 2002 +// Copyright Beman Dawes 2002-2005, 2009 +// Copyright Andrey Semashev 2021-2023 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +// path::stem(), extension(), and replace_extension() are based on +// basename(), extension(), and change_extension() from the original +// filesystem/convenience.hpp header by Vladimir Prus. + +#ifndef BOOST_FILESYSTEM_PATH_HPP +#define BOOST_FILESYSTEM_PATH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +#include +#endif + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +class path; + +namespace path_detail { // intentionally don't use filesystem::detail to not bring internal Boost.Filesystem functions into ADL via path_constants + +template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > +struct path_constants +{ + typedef path_constants< Char, Separator, PreferredSeparator, Dot > path_constants_base; + typedef Char value_type; + static BOOST_CONSTEXPR_OR_CONST value_type separator = Separator; + static BOOST_CONSTEXPR_OR_CONST value_type preferred_separator = PreferredSeparator; + static BOOST_CONSTEXPR_OR_CONST value_type dot = Dot; +}; + +#if defined(BOOST_NO_CXX17_INLINE_VARIABLES) +template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > +BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type +path_constants< Char, Separator, PreferredSeparator, Dot >::separator; +template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > +BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type +path_constants< Char, Separator, PreferredSeparator, Dot >::preferred_separator; +template< typename Char, Char Separator, Char PreferredSeparator, Char Dot > +BOOST_CONSTEXPR_OR_CONST typename path_constants< Char, Separator, PreferredSeparator, Dot >::value_type +path_constants< Char, Separator, PreferredSeparator, Dot >::dot; +#endif + +class path_iterator; +class path_reverse_iterator; + +} // namespace path_detail + +namespace detail { + +struct path_algorithms +{ + // A struct that denotes a contiguous range of characters in a string. A lightweight alternative to string_view. + struct substring + { + std::size_t pos; + std::size_t size; + }; + + typedef path_traits::path_native_char_type value_type; + typedef std::basic_string< value_type > string_type; + + static bool has_filename_v3(path const& p); + static bool has_filename_v4(path const& p); + BOOST_FILESYSTEM_DECL static path filename_v3(path const& p); + static path filename_v4(path const& p); + + BOOST_FILESYSTEM_DECL static path stem_v3(path const& p); + BOOST_FILESYSTEM_DECL static path stem_v4(path const& p); + BOOST_FILESYSTEM_DECL static path extension_v3(path const& p); + static path extension_v4(path const& p); + + BOOST_FILESYSTEM_DECL static void remove_filename_v3(path& p); + BOOST_FILESYSTEM_DECL static void remove_filename_v4(path& p); + + BOOST_FILESYSTEM_DECL static void replace_extension_v3(path& p, path const& new_extension); + BOOST_FILESYSTEM_DECL static void replace_extension_v4(path& p, path const& new_extension); + + BOOST_FILESYSTEM_DECL static path lexically_normal_v3(path const& p); + BOOST_FILESYSTEM_DECL static path lexically_normal_v4(path const& p); + + BOOST_FILESYSTEM_DECL static int compare_v3(path const& left, path const& right); + BOOST_FILESYSTEM_DECL static int compare_v4(path const& left, path const& right); + + BOOST_FILESYSTEM_DECL static void append_v3(path& p, const value_type* b, const value_type* e); + BOOST_FILESYSTEM_DECL static void append_v4(path& p, const value_type* b, const value_type* e); + static void append_v4(path& left, path const& right); + + // Returns: If separator is to be appended, m_pathname.size() before append. Otherwise 0. + // Note: An append is never performed if size()==0, so a returned 0 is unambiguous. + BOOST_FILESYSTEM_DECL static string_type::size_type append_separator_if_needed(path& p); + BOOST_FILESYSTEM_DECL static void erase_redundant_separator(path& p, string_type::size_type sep_pos); + + BOOST_FILESYSTEM_DECL static string_type::size_type find_root_name_size(path const& p); + BOOST_FILESYSTEM_DECL static string_type::size_type find_root_path_size(path const& p); + BOOST_FILESYSTEM_DECL static substring find_root_directory(path const& p); + BOOST_FILESYSTEM_DECL static substring find_relative_path(path const& p); + BOOST_FILESYSTEM_DECL static string_type::size_type find_parent_path_size(path const& p); + BOOST_FILESYSTEM_DECL static string_type::size_type find_filename_v4_size(path const& p); + BOOST_FILESYSTEM_DECL static string_type::size_type find_extension_v4_size(path const& p); + + BOOST_FILESYSTEM_DECL static int lex_compare_v3 + ( + path_detail::path_iterator first1, path_detail::path_iterator const& last1, + path_detail::path_iterator first2, path_detail::path_iterator const& last2 + ); + BOOST_FILESYSTEM_DECL static int lex_compare_v4 + ( + path_detail::path_iterator first1, path_detail::path_iterator const& last1, + path_detail::path_iterator first2, path_detail::path_iterator const& last2 + ); + + BOOST_FILESYSTEM_DECL static void increment_v3(path_detail::path_iterator& it); + BOOST_FILESYSTEM_DECL static void increment_v4(path_detail::path_iterator& it); + BOOST_FILESYSTEM_DECL static void decrement_v3(path_detail::path_iterator& it); + BOOST_FILESYSTEM_DECL static void decrement_v4(path_detail::path_iterator& it); +}; + +} // namespace detail + +//------------------------------------------------------------------------------------// +// // +// class path // +// // +//------------------------------------------------------------------------------------// + +class path : + public filesystem::path_detail::path_constants< +#ifdef BOOST_WINDOWS_API + detail::path_traits::path_native_char_type, L'/', L'\\', L'.' +#else + detail::path_traits::path_native_char_type, '/', '/', '.' +#endif + > +{ + friend class path_detail::path_iterator; + friend class path_detail::path_reverse_iterator; + friend struct detail::path_algorithms; + +public: + // value_type is the character type used by the operating system API to + // represent paths. + + typedef detail::path_algorithms::value_type value_type; + typedef detail::path_algorithms::string_type string_type; + typedef detail::path_traits::codecvt_type codecvt_type; + + // ----- character encoding conversions ----- + + // Following the principle of least astonishment, path input arguments + // passed to or obtained from the operating system via objects of + // class path behave as if they were directly passed to or + // obtained from the O/S API, unless conversion is explicitly requested. + // + // POSIX specfies that path strings are passed unchanged to and from the + // API. Note that this is different from the POSIX command line utilities, + // which convert according to a locale. + // + // Thus for POSIX, char strings do not undergo conversion. wchar_t strings + // are converted to/from char using the path locale or, if a conversion + // argument is given, using a conversion object modeled on + // std::wstring_convert. + // + // The path locale, which is global to the thread, can be changed by the + // imbue() function. It is initialized to an implementation defined locale. + // + // For Windows, wchar_t strings do not undergo conversion. char strings + // are converted using the "ANSI" or "OEM" code pages, as determined by + // the AreFileApisANSI() function, or, if a conversion argument is given, + // using a conversion object modeled on std::wstring_convert. + // + // See m_pathname comments for further important rationale. + + // TODO: rules needed for operating systems that use / or . + // differently, or format directory paths differently from file paths. + // + // ********************************************************************************** + // + // More work needed: How to handle an operating system that may have + // slash characters or dot characters in valid filenames, either because + // it doesn't follow the POSIX standard, or because it allows MBCS + // filename encodings that may contain slash or dot characters. For + // example, ISO/IEC 2022 (JIS) encoding which allows switching to + // JIS x0208-1983 encoding. A valid filename in this set of encodings is + // 0x1B 0x24 0x42 [switch to X0208-1983] 0x24 0x2F [U+304F Kiragana letter KU] + // ^^^^ + // Note that 0x2F is the ASCII slash character + // + // ********************************************************************************** + + // Supported source arguments: half-open iterator range, container, c-array, + // and single pointer to null terminated string. + + // All source arguments except pointers to null terminated byte strings support + // multi-byte character strings which may have embedded nulls. Embedded null + // support is required for some Asian languages on Windows. + + // "const codecvt_type& cvt=codecvt()" default arguments are not used because this + // limits the impact of locale("") initialization failures on POSIX systems to programs + // that actually depend on locale(""). It further ensures that exceptions thrown + // as a result of such failues occur after main() has started, so can be caught. + +private: + //! Assignment operation + class assign_op + { + private: + path& m_self; + + public: + typedef void result_type; + + explicit assign_op(path& self) BOOST_NOEXCEPT : m_self(self) {} + + result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const + { + m_self.m_pathname.assign(source, source_end); + } + + template< typename OtherChar > + result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const + { + m_self.m_pathname.clear(); + detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt); + } + }; + + //! Concatenation operation + class concat_op + { + private: + path& m_self; + + public: + typedef void result_type; + + explicit concat_op(path& self) BOOST_NOEXCEPT : m_self(self) {} + + result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const + { + m_self.m_pathname.append(source, source_end); + } + + template< typename OtherChar > + result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const + { + detail::path_traits::convert(source, source_end, m_self.m_pathname, cvt); + } + }; + + //! Path appending operation + class append_op + { + private: + path& m_self; + + public: + typedef void result_type; + + explicit append_op(path& self) BOOST_NOEXCEPT : m_self(self) {} + + BOOST_FORCEINLINE result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const + { + m_self.append(source, source_end); + } + + template< typename OtherChar > + BOOST_FORCEINLINE result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const + { + string_type src; + detail::path_traits::convert(source, source_end, src, cvt); + m_self.append(src.data(), src.data() + src.size()); + } + }; + + //! Path comparison operation + class compare_op + { + private: + path const& m_self; + + public: + typedef int result_type; + + explicit compare_op(path const& self) BOOST_NOEXCEPT : m_self(self) {} + + result_type operator() (const value_type* source, const value_type* source_end, const codecvt_type* = NULL) const; + + template< typename OtherChar > + result_type operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt = NULL) const; + }; + +public: + typedef path_detail::path_iterator iterator; + typedef iterator const_iterator; + typedef path_detail::path_reverse_iterator reverse_iterator; + typedef reverse_iterator const_reverse_iterator; + +public: + // ----- constructors ----- + + path() BOOST_NOEXCEPT {} + path(path const& p) : m_pathname(p.m_pathname) {} + path(path const& p, codecvt_type const&) : m_pathname(p.m_pathname) {} + + path(const value_type* s) : m_pathname(s) {} + path(const value_type* s, codecvt_type const&) : m_pathname(s) {} + path(string_type const& s) : m_pathname(s) {} + path(string_type const& s, codecvt_type const&) : m_pathname(s) {} +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + path(std::basic_string_view< value_type > const& s) : m_pathname(s) {} + path(std::basic_string_view< value_type > const& s, codecvt_type const&) : m_pathname(s) {} +#endif + +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template< + typename Source, + typename = typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > > + >::value + >::type + > + path(Source const& source) +#else + template< typename Source > + path(Source const& source, typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > > + >::value + >::type* = NULL) +#endif + { + assign(source); + } + +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template< + typename Source, + typename = typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > > + >::value + >::type + > + explicit path(Source const& source, codecvt_type const& cvt) +#else + template< typename Source > + explicit path(Source const& source, codecvt_type const& cvt, typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_native_path_source< typename boost::remove_cv< Source >::type > > + >::value + >::type* = NULL) +#endif + { + assign(source, cvt); + } + + // As of October 2015 the interaction between noexcept and =default is so troublesome + // for VC++, GCC, and probably other compilers, that =default is not used with noexcept + // functions. GCC is not even consistent for the same release on different platforms. + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + path(path&& p) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname)) + { + } + path(path&& p, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(p.m_pathname)) + { + } + path& operator=(path&& p) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p.m_pathname); + return *this; + } + path& assign(path&& p) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p.m_pathname); + return *this; + } + path& assign(path&& p, codecvt_type const&) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p.m_pathname); + return *this; + } + + path(string_type&& s) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s)) + { + } + path(string_type&& s, codecvt_type const&) BOOST_NOEXCEPT : m_pathname(static_cast< string_type&& >(s)) + { + } + path& operator=(string_type&& p) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p); + return *this; + } + path& assign(string_type&& p) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p); + return *this; + } + path& assign(string_type&& p, codecvt_type const&) BOOST_NOEXCEPT + { + m_pathname = static_cast< string_type&& >(p); + return *this; + } +#endif + + path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {} + path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {} + +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template< + typename InputIterator, + typename = typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value + >::type + > + path(InputIterator begin, InputIterator end) +#else + template< typename InputIterator > + path(InputIterator begin, InputIterator end, typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value + >::type* = NULL) +#endif + { + if (begin != end) + { + typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; + source_t source(begin, end); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + assign(static_cast< source_t&& >(source)); +#else + assign(source); +#endif + } + } + +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template< + typename InputIterator, + typename = typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value + >::type + > + path(InputIterator begin, InputIterator end, codecvt_type const& cvt) +#else + template< typename InputIterator > + path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value + >::type* = NULL) +#endif + { + if (begin != end) + { + typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; + source_t source(begin, end); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + assign(static_cast< source_t&& >(source), cvt); +#else + assign(source, cvt); +#endif + } + } + +#if !defined(BOOST_NO_CXX11_NULLPTR) + BOOST_DELETED_FUNCTION(path(std::nullptr_t)) + BOOST_DELETED_FUNCTION(path& operator= (std::nullptr_t)) +#endif + +public: + // ----- assignments ----- + + // We need to explicitly define copy assignment as otherwise it will be implicitly defined as deleted because there is move assignment + path& operator=(path const& p); + + template< typename Source > + typename boost::enable_if_c< + boost::disjunction< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + path& + >::type operator=(Source const& source) + { + return assign(source); + } + + path& assign(path const& p) + { + m_pathname = p.m_pathname; + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type assign(Source const& source) + { + detail::path_traits::dispatch(source, assign_op(*this)); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type assign(Source const& source) + { + detail::path_traits::dispatch_convertible(source, assign_op(*this)); + return *this; + } + + path& assign(path const& p, codecvt_type const&) + { + m_pathname = p.m_pathname; + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type assign(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch(source, assign_op(*this), &cvt); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type assign(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch_convertible(source, assign_op(*this), &cvt); + return *this; + } + + path& assign(const value_type* begin, const value_type* end) + { + m_pathname.assign(begin, end); + return *this; + } + + template< typename InputIterator > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type assign(InputIterator begin, InputIterator end) + { + m_pathname.clear(); + if (begin != end) + { + typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; + source_t source(begin, end); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + assign(static_cast< source_t&& >(source)); +#else + assign(source); +#endif + } + return *this; + } + + path& assign(const value_type* begin, const value_type* end, codecvt_type const&) + { + m_pathname.assign(begin, end); + return *this; + } + + template< typename InputIterator > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type assign(InputIterator begin, InputIterator end, codecvt_type const& cvt) + { + m_pathname.clear(); + if (begin != end) + { + typedef std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source_t; + source_t source(begin, end); +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + assign(static_cast< source_t&& >(source), cvt); +#else + assign(source, cvt); +#endif + } + return *this; + } + + // ----- concatenation ----- + + path& operator+=(path const& p); + + template< typename Source > + typename boost::enable_if_c< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type operator+=(Source const& source) + { + return concat(source); + } + + path& operator+=(value_type c) + { + m_pathname.push_back(c); + return *this; + } + + template< typename CharT > + typename boost::enable_if_c< + detail::path_traits::is_path_char_type< CharT >::value, + path& + >::type operator+=(CharT c) + { + CharT tmp[2]; + tmp[0] = c; + tmp[1] = static_cast< CharT >(0); + concat_op(*this)(tmp, tmp + 1); + return *this; + } + + path& concat(path const& p) + { + m_pathname.append(p.m_pathname); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type concat(Source const& source) + { + detail::path_traits::dispatch(source, concat_op(*this)); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type concat(Source const& source) + { + detail::path_traits::dispatch_convertible(source, concat_op(*this)); + return *this; + } + + path& concat(path const& p, codecvt_type const&) + { + m_pathname.append(p.m_pathname); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type concat(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch(source, concat_op(*this), &cvt); + return *this; + } + + template< typename Source > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type concat(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch_convertible(source, concat_op(*this), &cvt); + return *this; + } + + path& concat(const value_type* begin, const value_type* end) + { + m_pathname.append(begin, end); + return *this; + } + + template< typename InputIterator > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type concat(InputIterator begin, InputIterator end) + { + if (begin != end) + { + std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); + detail::path_traits::dispatch(source, concat_op(*this)); + } + return *this; + } + + path& concat(const value_type* begin, const value_type* end, codecvt_type const&) + { + m_pathname.append(begin, end); + return *this; + } + + template< typename InputIterator > + typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type concat(InputIterator begin, InputIterator end, codecvt_type const& cvt) + { + if (begin != end) + { + std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); + detail::path_traits::dispatch(source, concat_op(*this), &cvt); + } + return *this; + } + + // ----- appends ----- + + // if a separator is added, it is the preferred separator for the platform; + // slash for POSIX, backslash for Windows + + path& operator/=(path const& p); + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type operator/=(Source const& source) + { + return append(source); + } + + path& append(path const& p); + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type append(Source const& source) + { + detail::path_traits::dispatch(source, append_op(*this)); + return *this; + } + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type append(Source const& source) + { + detail::path_traits::dispatch_convertible(source, append_op(*this)); + return *this; + } + + path& append(path const& p, codecvt_type const&); + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + path& + >::type append(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch(source, append_op(*this), &cvt); + return *this; + } + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + path& + >::type append(Source const& source, codecvt_type const& cvt) + { + detail::path_traits::dispatch_convertible(source, append_op(*this), &cvt); + return *this; + } + + path& append(const value_type* begin, const value_type* end); + + template< typename InputIterator > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type append(InputIterator begin, InputIterator end) + { + std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); + detail::path_traits::dispatch(source, append_op(*this)); + return *this; + } + + path& append(const value_type* begin, const value_type* end, codecvt_type const&); + + template< typename InputIterator > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_path_source_iterator< InputIterator >, + boost::negation< detail::path_traits::is_native_char_ptr< InputIterator > > + >::value, + path& + >::type append(InputIterator begin, InputIterator end, const codecvt_type& cvt) + { + std::basic_string< typename std::iterator_traits< InputIterator >::value_type > source(begin, end); + detail::path_traits::dispatch(source, append_op(*this), &cvt); + return *this; + } + + // ----- modifiers ----- + + void clear() BOOST_NOEXCEPT { m_pathname.clear(); } +#ifdef BOOST_POSIX_API + path& make_preferred() + { + // No effect on POSIX + return *this; + } +#else // BOOST_WINDOWS_API + BOOST_FILESYSTEM_DECL path& make_preferred(); // change slashes to backslashes +#endif + path& remove_filename(); + BOOST_FILESYSTEM_DECL path& remove_filename_and_trailing_separators(); + BOOST_FILESYSTEM_DECL path& remove_trailing_separator(); + BOOST_FILESYSTEM_DECL path& replace_filename(path const& replacement); + path& replace_extension(path const& new_extension = path()); + + void swap(path& rhs) BOOST_NOEXCEPT { m_pathname.swap(rhs.m_pathname); } + + // ----- observers ----- + + // For operating systems that format file paths differently than directory + // paths, return values from observers are formatted as file names unless there + // is a trailing separator, in which case returns are formatted as directory + // paths. POSIX and Windows make no such distinction. + + // Implementations are permitted to return const values or const references. + + // The string or path returned by an observer are specified as being formatted + // as "native" or "generic". + // + // For POSIX, these are all the same format; slashes and backslashes are as input and + // are not modified. + // + // For Windows, native: as input; slashes and backslashes are not modified; + // this is the format of the internally stored string. + // generic: backslashes are converted to slashes + + // ----- native format observers ----- + + string_type const& native() const BOOST_NOEXCEPT { return m_pathname; } + const value_type* c_str() const BOOST_NOEXCEPT { return m_pathname.c_str(); } + string_type::size_type size() const BOOST_NOEXCEPT { return m_pathname.size(); } + + template< typename String > + String string() const; + + template< typename String > + String string(codecvt_type const& cvt) const; + +#ifdef BOOST_WINDOWS_API + std::string string() const + { + std::string tmp; + if (!m_pathname.empty()) + detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp); + return tmp; + } + std::string string(codecvt_type const& cvt) const + { + std::string tmp; + if (!m_pathname.empty()) + detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt); + return tmp; + } + + // string_type is std::wstring, so there is no conversion + std::wstring const& wstring() const { return m_pathname; } + std::wstring const& wstring(codecvt_type const&) const { return m_pathname; } +#else // BOOST_POSIX_API + // string_type is std::string, so there is no conversion + std::string const& string() const { return m_pathname; } + std::string const& string(codecvt_type const&) const { return m_pathname; } + + std::wstring wstring() const + { + std::wstring tmp; + if (!m_pathname.empty()) + detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp); + return tmp; + } + std::wstring wstring(codecvt_type const& cvt) const + { + std::wstring tmp; + if (!m_pathname.empty()) + detail::path_traits::convert(m_pathname.data(), m_pathname.data() + m_pathname.size(), tmp, &cvt); + return tmp; + } +#endif + + // ----- generic format observers ----- + + // Experimental generic function returning generic formatted path (i.e. separators + // are forward slashes). Motivation: simpler than a family of generic_*string + // functions. +#ifdef BOOST_WINDOWS_API + BOOST_FILESYSTEM_DECL path generic_path() const; +#else + path generic_path() const; +#endif + + template< typename String > + String generic_string() const; + + template< typename String > + String generic_string(codecvt_type const& cvt) const; + +#ifdef BOOST_WINDOWS_API + std::string generic_string() const { return generic_path().string(); } + std::string generic_string(codecvt_type const& cvt) const { return generic_path().string(cvt); } + std::wstring generic_wstring() const { return generic_path().wstring(); } + std::wstring generic_wstring(codecvt_type const&) const { return generic_wstring(); } +#else // BOOST_POSIX_API + // On POSIX-like systems, the generic format is the same as the native format + std::string const& generic_string() const { return m_pathname; } + std::string const& generic_string(codecvt_type const&) const { return m_pathname; } + std::wstring generic_wstring() const { return this->wstring(); } + std::wstring generic_wstring(codecvt_type const& cvt) const { return this->wstring(cvt); } +#endif + + // ----- compare ----- + + int compare(path const& p) const; // generic, lexicographical + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + int + >::type compare(Source const& source) const + { + return detail::path_traits::dispatch(source, compare_op(*this)); + } + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + int + >::type compare(Source const& source) const + { + return detail::path_traits::dispatch_convertible(source, compare_op(*this)); + } + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type >::value, + int + >::type compare(Source const& source, codecvt_type const& cvt) const + { + return detail::path_traits::dispatch(source, compare_op(*this), &cvt); + } + + template< typename Source > + BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >, + boost::negation< detail::path_traits::is_path_source< typename boost::remove_cv< Source >::type > > + >::value, + int + >::type compare(Source const& source, codecvt_type const& cvt) const + { + return detail::path_traits::dispatch_convertible(source, compare_op(*this), &cvt); + } + + // ----- decomposition ----- + + path root_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_path_size(*this)); } + // returns 0 or 1 element path even on POSIX, root_name() is non-empty() for network paths + path root_name() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_root_name_size(*this)); } + + // returns 0 or 1 element path + path root_directory() const + { + detail::path_algorithms::substring root_dir = detail::path_algorithms::find_root_directory(*this); + const value_type* p = m_pathname.c_str() + root_dir.pos; + return path(p, p + root_dir.size); + } + + path relative_path() const + { + detail::path_algorithms::substring rel_path = detail::path_algorithms::find_relative_path(*this); + const value_type* p = m_pathname.c_str() + rel_path.pos; + return path(p, p + rel_path.size); + } + + path parent_path() const { return path(m_pathname.c_str(), m_pathname.c_str() + detail::path_algorithms::find_parent_path_size(*this)); } + + path filename() const; // returns 0 or 1 element path + path stem() const; // returns 0 or 1 element path + path extension() const; // returns 0 or 1 element path + + // ----- query ----- + + bool empty() const BOOST_NOEXCEPT { return m_pathname.empty(); } + bool filename_is_dot() const; + bool filename_is_dot_dot() const; + bool has_root_path() const { return detail::path_algorithms::find_root_path_size(*this) > 0; } + bool has_root_name() const { return detail::path_algorithms::find_root_name_size(*this) > 0; } + bool has_root_directory() const { return detail::path_algorithms::find_root_directory(*this).size > 0; } + bool has_relative_path() const { return detail::path_algorithms::find_relative_path(*this).size > 0; } + bool has_parent_path() const { return detail::path_algorithms::find_parent_path_size(*this) > 0; } + bool has_filename() const; + bool has_stem() const { return !stem().empty(); } + bool has_extension() const { return !extension().empty(); } + bool is_relative() const { return !is_absolute(); } + bool is_absolute() const + { + // Windows CE has no root name (aka drive letters) +#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) + return has_root_name() && has_root_directory(); +#else + return has_root_directory(); +#endif + } + + // ----- lexical operations ----- + + path lexically_normal() const; + BOOST_FILESYSTEM_DECL path lexically_relative(path const& base) const; + path lexically_proximate(path const& base) const; + + // ----- iterators ----- + + BOOST_FILESYSTEM_DECL iterator begin() const; + BOOST_FILESYSTEM_DECL iterator end() const; + reverse_iterator rbegin() const; + reverse_iterator rend() const; + + // ----- static member functions ----- + + static BOOST_FILESYSTEM_DECL std::locale imbue(std::locale const& loc); + static BOOST_FILESYSTEM_DECL codecvt_type const& codecvt(); + + // ----- deprecated functions ----- + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + // recently deprecated functions supplied by default + path& normalize(); + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::remove_filename() instead") + path& remove_leaf() { return remove_filename(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::filename() instead") + path leaf() const { return filename(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::parent_path() instead") + path branch_path() const { return parent_path(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::generic_path() instead") + path generic() const { return generic_path(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use !path::empty() instead") + bool has_leaf() const { return !m_pathname.empty(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::has_parent_path() instead") + bool has_branch_path() const { return has_parent_path(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::is_absolute() instead") + bool is_complete() const { return is_absolute(); } +#endif + +#if defined(BOOST_FILESYSTEM_DEPRECATED) + // deprecated functions with enough signature or semantic changes that they are + // not supplied by default + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead") + std::string file_string() const { return string(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead") + std::string directory_string() const { return string(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead") + std::string native_file_string() const { return string(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::string() instead") + std::string native_directory_string() const { return string(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead") + string_type external_file_string() const { return native(); } + BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::native() instead") + string_type external_directory_string() const { return native(); } +#endif + + //--------------------------------------------------------------------------------------// + // class path private members // + //--------------------------------------------------------------------------------------// +private: + /* + * m_pathname has the type, encoding, and format required by the native + * operating system. Thus for POSIX and Windows there is no conversion for + * passing m_pathname.c_str() to the O/S API or when obtaining a path from the + * O/S API. POSIX encoding is unspecified other than for dot and slash + * characters; POSIX just treats paths as a sequence of bytes. Windows + * encoding is UCS-2 or UTF-16 depending on the version. + */ + string_type m_pathname; // Windows: as input; backslashes NOT converted to slashes, + // slashes NOT converted to backslashes +}; + +namespace detail { +BOOST_FILESYSTEM_DECL path const& dot_path(); +BOOST_FILESYSTEM_DECL path const& dot_dot_path(); +} // namespace detail + +#ifndef BOOST_FILESYSTEM_NO_DEPRECATED +typedef path wpath; +#endif + +namespace path_detail { + +//------------------------------------------------------------------------------------// +// class path::iterator // +//------------------------------------------------------------------------------------// + +class path_iterator : + public boost::iterator_facade< + path_iterator, + const path, + boost::bidirectional_traversal_tag + > +{ +private: + friend class boost::iterator_core_access; + friend class boost::filesystem::path; + friend class path_reverse_iterator; + friend struct boost::filesystem::detail::path_algorithms; + + path const& dereference() const { return m_element; } + + bool equal(path_iterator const& rhs) const BOOST_NOEXCEPT + { + return m_path_ptr == rhs.m_path_ptr && m_pos == rhs.m_pos; + } + + void increment(); + void decrement(); + +private: + // current element + path m_element; + // path being iterated over + const path* m_path_ptr; + // position of m_element in m_path_ptr->m_pathname. + // if m_element is implicit dot, m_pos is the + // position of the last separator in the path. + // end() iterator is indicated by + // m_pos == m_path_ptr->m_pathname.size() + path::string_type::size_type m_pos; +}; + +//------------------------------------------------------------------------------------// +// class path::reverse_iterator // +//------------------------------------------------------------------------------------// + +class path_reverse_iterator : + public boost::iterator_facade< + path_reverse_iterator, + const path, + boost::bidirectional_traversal_tag + > +{ +public: + explicit path_reverse_iterator(path_iterator itr) : + m_itr(itr) + { + if (itr != itr.m_path_ptr->begin()) + m_element = *--itr; + } + +private: + friend class boost::iterator_core_access; + friend class boost::filesystem::path; + + path const& dereference() const { return m_element; } + bool equal(path_reverse_iterator const& rhs) const BOOST_NOEXCEPT { return m_itr == rhs.m_itr; } + + void increment() + { + --m_itr; + if (m_itr != m_itr.m_path_ptr->begin()) + { + path_iterator tmp = m_itr; + m_element = *--tmp; + } + } + + void decrement() + { + m_element = *m_itr; + ++m_itr; + } + +private: + path_iterator m_itr; + path m_element; +}; + +// std::lexicographical_compare would infinitely recurse because path iterators +// yield paths, so provide a path aware version +bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2); + +} // namespace path_detail + +using path_detail::lexicographical_compare; + +//------------------------------------------------------------------------------------// +// // +// non-member functions // +// // +//------------------------------------------------------------------------------------// + +BOOST_FORCEINLINE bool operator==(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) == 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator==(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) == 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator==(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) == 0; +} + +BOOST_FORCEINLINE bool operator!=(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) != 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator!=(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) != 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator!=(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) != 0; +} + +BOOST_FORCEINLINE bool operator<(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) < 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator<(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) < 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator<(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) > 0; +} + +BOOST_FORCEINLINE bool operator<=(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) <= 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator<=(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) <= 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator<=(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) >= 0; +} + +BOOST_FORCEINLINE bool operator>(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) > 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator>(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) > 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator>(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) < 0; +} + +BOOST_FORCEINLINE bool operator>=(path const& lhs, path const& rhs) +{ + return lhs.compare(rhs) >= 0; +} + +template< typename Path, typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator>=(Path const& lhs, Source const& rhs) +{ + return lhs.compare(rhs) >= 0; +} + +template< typename Source, typename Path > +BOOST_FORCEINLINE typename boost::enable_if_c< + boost::conjunction< + boost::is_same< Path, path >, + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type > + >::value, + bool +>::type operator>=(Source const& lhs, Path const& rhs) +{ + return rhs.compare(lhs) <= 0; +} + + +// Note: Declared as a template to delay binding to Boost.ContainerHash functions and make the dependency optional +template< typename Path > +inline typename boost::enable_if_c< + boost::is_same< Path, path >::value, + std::size_t +>::type hash_value(Path const& p) BOOST_NOEXCEPT +{ +#ifdef BOOST_WINDOWS_API + std::size_t seed = 0u; + for (typename Path::value_type const* it = p.c_str(); *it; ++it) + hash_combine(seed, *it == L'/' ? L'\\' : *it); + return seed; +#else // BOOST_POSIX_API + return hash_range(p.native().begin(), p.native().end()); +#endif +} + +inline void swap(path& lhs, path& rhs) BOOST_NOEXCEPT +{ + lhs.swap(rhs); +} + +BOOST_FORCEINLINE path operator/(path lhs, path const& rhs) +{ + lhs.append(rhs); + return lhs; +} + +template< typename Source > +BOOST_FORCEINLINE typename boost::enable_if_c< + detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value, + path +>::type operator/(path lhs, Source const& rhs) +{ + lhs.append(rhs); + return lhs; +} + +// inserters and extractors +// use boost::io::quoted() to handle spaces in paths +// use '&' as escape character to ease use for Windows paths + +template< typename Char, typename Traits > +inline std::basic_ostream< Char, Traits >& +operator<<(std::basic_ostream< Char, Traits >& os, path const& p) +{ + return os << boost::io::quoted(p.template string< std::basic_string< Char > >(), static_cast< Char >('&')); +} + +template< typename Char, typename Traits > +inline std::basic_istream< Char, Traits >& +operator>>(std::basic_istream< Char, Traits >& is, path& p) +{ + std::basic_string< Char > str; + is >> boost::io::quoted(str, static_cast< Char >('&')); + p = str; + return is; +} + +// name_checks + +// These functions are holdovers from version 1. It isn't clear they have much +// usefulness, or how to generalize them for later versions. + +BOOST_FILESYSTEM_DECL bool portable_posix_name(std::string const& name); +BOOST_FILESYSTEM_DECL bool windows_name(std::string const& name); +BOOST_FILESYSTEM_DECL bool portable_name(std::string const& name); +BOOST_FILESYSTEM_DECL bool portable_directory_name(std::string const& name); +BOOST_FILESYSTEM_DECL bool portable_file_name(std::string const& name); +BOOST_FILESYSTEM_DECL bool native(std::string const& name); + +namespace detail { + +// For POSIX, is_directory_separator() and is_element_separator() are identical since +// a forward slash is the only valid directory separator and also the only valid +// element separator. For Windows, forward slash and back slash are the possible +// directory separators, but colon (example: "c:foo") is also an element separator. +inline bool is_directory_separator(path::value_type c) BOOST_NOEXCEPT +{ + return c == path::separator +#ifdef BOOST_WINDOWS_API + || c == path::preferred_separator +#endif + ; +} + +inline bool is_element_separator(path::value_type c) BOOST_NOEXCEPT +{ + return c == path::separator +#ifdef BOOST_WINDOWS_API + || c == path::preferred_separator || c == L':' +#endif + ; +} + +} // namespace detail + +//------------------------------------------------------------------------------------// +// class path miscellaneous function implementations // +//------------------------------------------------------------------------------------// + +namespace detail { + +inline bool path_algorithms::has_filename_v3(path const& p) +{ + return !p.m_pathname.empty(); +} + +inline bool path_algorithms::has_filename_v4(path const& p) +{ + return path_algorithms::find_filename_v4_size(p) > 0; +} + +inline path path_algorithms::filename_v4(path const& p) +{ + string_type::size_type filename_size = path_algorithms::find_filename_v4_size(p); + string_type::size_type pos = p.m_pathname.size() - filename_size; + const value_type* ptr = p.m_pathname.c_str() + pos; + return path(ptr, ptr + filename_size); +} + +inline path path_algorithms::extension_v4(path const& p) +{ + string_type::size_type extension_size = path_algorithms::find_extension_v4_size(p); + string_type::size_type pos = p.m_pathname.size() - extension_size; + const value_type* ptr = p.m_pathname.c_str() + pos; + return path(ptr, ptr + extension_size); +} + +inline void path_algorithms::append_v4(path& left, path const& right) +{ + path_algorithms::append_v4(left, right.m_pathname.c_str(), right.m_pathname.c_str() + right.m_pathname.size()); +} + +} // namespace detail + +// Note: Because of the range constructor in C++23 std::string_view that involves a check for contiguous_range concept, +// any non-template function call that requires a check whether the source argument (which may be fs::path) +// is convertible to std::string_view must be made after fs::path::iterator is defined. This includes overload +// resolution and SFINAE checks. Otherwise, the concept check result formally changes between fs::path::iterator +// is not defined and defined, which causes compilation errors with gcc 11 and later. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106808 + +BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const value_type* source, const value_type* source_end, const codecvt_type*) const +{ + path src; + src.m_pathname.assign(source, source_end); + return m_self.compare(src); +} + +template< typename OtherChar > +BOOST_FORCEINLINE path::compare_op::result_type path::compare_op::operator() (const OtherChar* source, const OtherChar* source_end, const codecvt_type* cvt) const +{ + path src; + detail::path_traits::convert(source, source_end, src.m_pathname, cvt); + return m_self.compare(src); +} + +inline path& path::operator=(path const& p) +{ + return assign(p); +} + +inline path& path::operator+=(path const& p) +{ + return concat(p); +} + +BOOST_FORCEINLINE path& path::operator/=(path const& p) +{ + return append(p); +} + +#if !defined(BOOST_WINDOWS_API) +inline path path::generic_path() const +{ + return path(*this); +} +#endif + +inline path path::lexically_proximate(path const& base) const +{ + path tmp(lexically_relative(base)); + return tmp.empty() ? *this : tmp; +} + +inline path::reverse_iterator path::rbegin() const +{ + return reverse_iterator(end()); +} + +inline path::reverse_iterator path::rend() const +{ + return reverse_iterator(begin()); +} + +inline bool path::filename_is_dot() const +{ + // implicit dot is tricky, so actually call filename(); see path::filename() example + // in reference.html + path p(filename()); + return p.size() == 1 && *p.c_str() == dot; +} + +inline bool path::filename_is_dot_dot() const +{ + return size() >= 2 && m_pathname[size() - 1] == dot && m_pathname[size() - 2] == dot && (m_pathname.size() == 2 || detail::is_element_separator(m_pathname[size() - 3])); + // use detail::is_element_separator() rather than detail::is_directory_separator + // to deal with "c:.." edge case on Windows when ':' acts as a separator +} + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use path::lexically_normal() instead") +BOOST_FORCEINLINE path& path::normalize() +{ + path tmp(lexically_normal()); + m_pathname.swap(tmp.m_pathname); + return *this; +} + +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + +// The following functions are defined differently, depending on Boost.Filesystem version in use. +// To avoid ODR violation, these functions are not defined when the library itself is built. +// This makes sure they are not compiled when the library is built, and the only version there is +// is the one in user's code. Users are supposed to consistently use the same Boost.Filesystem version +// in all their translation units. +#if !defined(BOOST_FILESYSTEM_SOURCE) + +BOOST_FORCEINLINE path& path::append(path const& p) +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size()); + return *this; +} + +BOOST_FORCEINLINE path& path::append(path const& p, codecvt_type const&) +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, p.m_pathname.data(), p.m_pathname.data() + p.m_pathname.size()); + return *this; +} + +BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end) +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end); + return *this; +} + +BOOST_FORCEINLINE path& path::append(const value_type* begin, const value_type* end, codecvt_type const&) +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::append)(*this, begin, end); + return *this; +} + +BOOST_FORCEINLINE path& path::remove_filename() +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::remove_filename)(*this); + return *this; +} + +BOOST_FORCEINLINE path& path::replace_extension(path const& new_extension) +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::replace_extension)(*this, new_extension); + return *this; +} + +BOOST_FORCEINLINE int path::compare(path const& p) const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::compare)(*this, p); +} + +BOOST_FORCEINLINE path path::filename() const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::filename)(*this); +} + +BOOST_FORCEINLINE path path::stem() const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::stem)(*this); +} + +BOOST_FORCEINLINE path path::extension() const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::extension)(*this); +} + +BOOST_FORCEINLINE bool path::has_filename() const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::has_filename)(*this); +} + +BOOST_FORCEINLINE path path::lexically_normal() const +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lexically_normal)(*this); +} + +namespace path_detail { + +BOOST_FORCEINLINE void path_iterator::increment() +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::increment)(*this); +} + +BOOST_FORCEINLINE void path_iterator::decrement() +{ + BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::decrement)(*this); +} + +BOOST_FORCEINLINE bool lexicographical_compare(path_iterator first1, path_iterator const& last1, path_iterator first2, path_iterator const& last2) +{ + return BOOST_FILESYSTEM_VERSIONED_SYM(detail::path_algorithms::lex_compare)(first1, last1, first2, last2) < 0; +} + +} // namespace path_detail + +#endif // !defined(BOOST_FILESYSTEM_SOURCE) + +//--------------------------------------------------------------------------------------// +// class path member template specializations // +//--------------------------------------------------------------------------------------// + +template< > +inline std::string path::string< std::string >() const +{ + return string(); +} + +template< > +inline std::wstring path::string< std::wstring >() const +{ + return wstring(); +} + +template< > +inline std::string path::string< std::string >(codecvt_type const& cvt) const +{ + return string(cvt); +} + +template< > +inline std::wstring path::string< std::wstring >(codecvt_type const& cvt) const +{ + return wstring(cvt); +} + +template< > +inline std::string path::generic_string< std::string >() const +{ + return generic_string(); +} + +template< > +inline std::wstring path::generic_string< std::wstring >() const +{ + return generic_wstring(); +} + +template< > +inline std::string path::generic_string< std::string >(codecvt_type const& cvt) const +{ + return generic_string(cvt); +} + +template< > +inline std::wstring path::generic_string< std::wstring >(codecvt_type const& cvt) const +{ + return generic_wstring(cvt); +} + +} // namespace filesystem +} // namespace boost + +//----------------------------------------------------------------------------// + +#include + +#endif // BOOST_FILESYSTEM_PATH_HPP diff --git a/boost/filesystem/string_file.hpp b/boost/filesystem/string_file.hpp new file mode 100644 index 0000000..29428c8 --- /dev/null +++ b/boost/filesystem/string_file.hpp @@ -0,0 +1,70 @@ +// filesystem/string_file.hpp --------------------------------------------------------// + +// Copyright Beman Dawes 2015 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#ifndef BOOST_FILESYSTEM_STRING_FILE_HPP +#define BOOST_FILESYSTEM_STRING_FILE_HPP + +#include + +#if !defined(BOOST_FILESYSTEM_DEPRECATED) && !defined(BOOST_FILESYSTEM_ALLOW_DEPRECATED) +#include +BOOST_HEADER_DEPRECATED("your own implementation") +#endif + +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use file IO streams instead") +inline void save_string_file(path const& p, std::string const& str) +{ + filesystem::ofstream file; + file.exceptions(std::ios_base::failbit | std::ios_base::badbit); + file.open(p, std::ios_base::binary); + const std::size_t sz = str.size(); + if (BOOST_UNLIKELY(sz > static_cast< boost::uintmax_t >((std::numeric_limits< std::streamsize >::max)()))) + BOOST_FILESYSTEM_THROW(std::length_error("String size exceeds max write size")); + file.write(str.c_str(), static_cast< std::streamsize >(sz)); +} + +BOOST_FILESYSTEM_DETAIL_DEPRECATED("Use file IO streams instead") +inline void load_string_file(path const& p, std::string& str) +{ + filesystem::ifstream file; + file.exceptions(std::ios_base::failbit | std::ios_base::badbit); + file.open(p, std::ios_base::binary); + const boost::uintmax_t sz = filesystem::file_size(p); + if (BOOST_UNLIKELY(sz > static_cast< boost::uintmax_t >((std::numeric_limits< std::streamsize >::max)()))) + BOOST_FILESYSTEM_THROW(std::length_error("File size exceeds max read size")); + str.resize(static_cast< std::size_t >(sz), '\0'); + if (sz > 0u) + file.read(&str[0], static_cast< std::streamsize >(sz)); +} + +} // namespace filesystem +} // namespace boost + +#include + +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) + +#endif // BOOST_FILESYSTEM_STRING_FILE_HPP diff --git a/boost/function/detail/requires_cxx11.hpp b/boost/function/detail/requires_cxx11.hpp index a68da21..a2da96c 100644 --- a/boost/function/detail/requires_cxx11.hpp +++ b/boost/function/detail/requires_cxx11.hpp @@ -15,7 +15,7 @@ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Function 1.82 and will be removed in Boost.Function 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.Function 1.82 and will be removed in Boost.Function 1.84. Please open an issue in https://github.com/boostorg/function if you want it retained.") #endif diff --git a/boost/integer/common_factor_ct.hpp b/boost/integer/common_factor_ct.hpp deleted file mode 100644 index 5769fa2..0000000 --- a/boost/integer/common_factor_ct.hpp +++ /dev/null @@ -1,102 +0,0 @@ -// Boost common_factor_ct.hpp header file ----------------------------------// - -// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) - -// See https://www.boost.org for updates, documentation, and revision history. - -#ifndef BOOST_INTEGER_COMMON_FACTOR_CT_HPP -#define BOOST_INTEGER_COMMON_FACTOR_CT_HPP - -#include // self include -#include // for BOOST_STATIC_CONSTANT, etc. - -namespace boost -{ -namespace integer -{ - -// Implementation details --------------------------------------------------// - -namespace detail -{ - // Build GCD with Euclid's recursive algorithm - template < static_gcd_type Value1, static_gcd_type Value2 > - struct static_gcd_helper_t - { - private: - BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 ); - BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 ); - - #ifndef BOOST_BORLANDC - #define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast(Value) - #else - typedef static_gcd_helper_t self_type; - #define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value ) - #endif - - typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1), - BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type; - - #undef BOOST_DETAIL_GCD_HELPER_VAL - - public: - BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value ); - }; - - // Non-recursive case - template < static_gcd_type Value1 > - struct static_gcd_helper_t< Value1, 0UL > - { - BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 ); - }; - - // Build the LCM from the GCD - template < static_gcd_type Value1, static_gcd_type Value2 > - struct static_lcm_helper_t - { - typedef static_gcd_helper_t gcd_type; - - BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value - * Value2 ); - }; - - // Special case for zero-GCD values - template < > - struct static_lcm_helper_t< 0UL, 0UL > - { - BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL ); - }; - -} // namespace detail - - -// Compile-time greatest common divisor evaluator class declaration --------// - -template < static_gcd_type Value1, static_gcd_type Value2 > struct static_gcd -{ - BOOST_STATIC_CONSTANT( static_gcd_type, value = (detail::static_gcd_helper_t::value) ); -}; // boost::integer::static_gcd - -#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) -template< static_gcd_type Value1, static_gcd_type Value2 > static_gcd_type const static_gcd< Value1, Value2 >::value; -#endif - -// Compile-time least common multiple evaluator class declaration ----------// - -template < static_gcd_type Value1, static_gcd_type Value2 > struct static_lcm -{ - BOOST_STATIC_CONSTANT( static_gcd_type, value = (detail::static_lcm_helper_t::value) ); -}; // boost::integer::static_lcm - -#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) -template< static_gcd_type Value1, static_gcd_type Value2 > static_gcd_type const static_lcm< Value1, Value2 >::value; -#endif - -} // namespace integer -} // namespace boost - - -#endif // BOOST_INTEGER_COMMON_FACTOR_CT_HPP diff --git a/boost/io/detail/buffer_fill.hpp b/boost/io/detail/buffer_fill.hpp new file mode 100644 index 0000000..b25a884 --- /dev/null +++ b/boost/io/detail/buffer_fill.hpp @@ -0,0 +1,39 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_BUFFER_FILL_HPP +#define BOOST_IO_DETAIL_BUFFER_FILL_HPP + +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +inline bool +buffer_fill(std::basic_streambuf& buf, charT ch, + std::size_t size) +{ + charT fill[] = { ch, ch, ch, ch, ch, ch, ch, ch }; + enum { + chunk = sizeof fill / sizeof(charT) + }; + for (; size > chunk; size -= chunk) { + if (static_cast(buf.sputn(fill, chunk)) != chunk) { + return false; + } + } + return static_cast(buf.sputn(fill, size)) == size; +} + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/boost/io/detail/ostream_guard.hpp b/boost/io/detail/ostream_guard.hpp new file mode 100644 index 0000000..6999d81 --- /dev/null +++ b/boost/io/detail/ostream_guard.hpp @@ -0,0 +1,45 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_OSTREAM_GUARD_HPP +#define BOOST_IO_DETAIL_OSTREAM_GUARD_HPP + +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +class ostream_guard { +public: + explicit ostream_guard(std::basic_ostream& os) BOOST_NOEXCEPT + : os_(&os) { } + + ~ostream_guard() BOOST_NOEXCEPT_IF(false) { + if (os_) { + os_->setstate(std::basic_ostream::badbit); + } + } + + void release() BOOST_NOEXCEPT { + os_ = 0; + } + +private: + ostream_guard(const ostream_guard&); + ostream_guard& operator=(const ostream_guard&); + + std::basic_ostream* os_; +}; + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/boost/io/quoted.hpp b/boost/io/quoted.hpp new file mode 100644 index 0000000..fc7d205 --- /dev/null +++ b/boost/io/quoted.hpp @@ -0,0 +1,217 @@ +/* +Copyright 2010 Beman Dawes + +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_QUOTED_HPP +#define BOOST_IO_QUOTED_HPP + +#include +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +struct quoted_proxy { + String string; + Char escape; + Char delim; +}; + +template +struct quoted_state { + const Char* string; + std::size_t size; + std::size_t count; +}; + +template +inline quoted_state +quoted_start(const Char* string, Char escape, Char delim) +{ + const Char* end = string; + std::size_t count = 2; + for (Char ch; (ch = *end) != 0; ++end) { + count += 1 + (ch == escape || ch == delim); + } + quoted_state state = { string, + static_cast(end - string), count }; + return state; +} + +template +inline quoted_state +quoted_start(const String* string, Char escape, Char delim) +{ + const Char* begin = string->data(); + std::size_t size = string->size(); + std::size_t count = 2; + for (const Char *it = begin, *end = begin + size; it != end; ++it) { + Char ch = *it; + count += 1 + (ch == escape || ch == delim); + } + quoted_state state = { begin, size, count }; + return state; +} + +template +inline bool +quoted_put(std::basic_streambuf& buf, const Char* string, + std::size_t size, std::size_t count, Char escape, Char delim) +{ + if (buf.sputc(delim) == Traits::eof()) { + return false; + } + if (size == count) { + if (static_cast(buf.sputn(string, size)) != size) { + return false; + } + } else { + for (const Char* end = string + size; string != end; ++string) { + Char ch = *string; + if ((ch == escape || ch == delim) && + buf.sputc(escape) == Traits::eof()) { + return false; + } + if (buf.sputc(ch) == Traits::eof()) { + return false; + } + } + } + return buf.sputc(delim) != Traits::eof(); +} + +template +inline std::basic_ostream& +quoted_out(std::basic_ostream& os, String* string, Char escape, + Char delim) +{ + typedef std::basic_ostream stream; + ostream_guard guard(os); + typename stream::sentry entry(os); + if (entry) { + quoted_state state = boost::io::detail::quoted_start(string, + escape, delim); + std::basic_streambuf& buf = *os.rdbuf(); + std::size_t width = static_cast(os.width()); + if (width <= state.count) { + if (!boost::io::detail::quoted_put(buf, state.string, state.size, + state.count, escape, delim)) { + return os; + } + } else if ((os.flags() & stream::adjustfield) == stream::left) { + if (!boost::io::detail::quoted_put(buf, state.string, state.size, + state.count, escape, delim) || + !boost::io::detail::buffer_fill(buf, os.fill(), + width - state.count)) { + return os; + } + } else if (!boost::io::detail::buffer_fill(buf, os.fill(), + width - state.count) || + !boost::io::detail::quoted_put(buf, state.string, state.size, + state.count, escape, delim)) { + return os; + } + os.width(0); + } + guard.release(); + return os; +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy& proxy) +{ + return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, + proxy.delim); +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy*, + Char>& proxy) +{ + return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, + proxy.delim); +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& os, + const quoted_proxy*, Char>& proxy) +{ + return boost::io::detail::quoted_out(os, proxy.string, proxy.escape, + proxy.delim); +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& is, + const quoted_proxy*, Char>& proxy) +{ + Char ch; + if (!(is >> ch)) { + return is; + } + if (ch != proxy.delim) { + is.unget(); + return is >> *proxy.string; + } + { + boost::io::ios_flags_saver ifs(is); + std::noskipws(is); + proxy.string->clear(); + while ((is >> ch) && ch != proxy.delim) { + if (ch == proxy.escape && !(is >> ch)) { + break; + } + proxy.string->push_back(ch); + } + } + return is; +} + +} /* detail */ + +template +inline detail::quoted_proxy*, + Char> +quoted(const std::basic_string& s, Char escape='\\', + Char delim='\"') +{ + detail::quoted_proxy*, + Char> proxy = { &s, escape, delim }; + return proxy; +} + +template +inline detail::quoted_proxy*, Char> +quoted(std::basic_string& s, Char escape='\\', + Char delim='\"') +{ + detail::quoted_proxy*, + Char> proxy = { &s, escape, delim }; + return proxy; +} + +template +inline detail::quoted_proxy +quoted(const Char* s, Char escape='\\', Char delim='\"') +{ + detail::quoted_proxy proxy = { s, escape, delim }; + return proxy; +} + +} /* io */ +} /* boost */ + +#endif diff --git a/boost/iterator/detail/facade_iterator_category.hpp b/boost/iterator/detail/facade_iterator_category.hpp index 6db45e4..9d41320 100644 --- a/boost/iterator/detail/facade_iterator_category.hpp +++ b/boost/iterator/detail/facade_iterator_category.hpp @@ -13,15 +13,14 @@ # include # include # include -# include + +# include # include # include # include # include -# include - # include // try to keep this last # ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY @@ -139,17 +138,17 @@ struct iterator_category_with_traversal // Make sure this isn't used to build any categories where // convertibility to Traversal is redundant. Should just use the // Category element in that case. - BOOST_MPL_ASSERT_NOT(( - is_convertible< + BOOST_STATIC_ASSERT(( + !is_convertible< typename iterator_category_to_traversal::type , Traversal - >)); + >::value)); - BOOST_MPL_ASSERT((is_iterator_category)); - BOOST_MPL_ASSERT_NOT((is_iterator_category)); - BOOST_MPL_ASSERT_NOT((is_iterator_traversal)); + BOOST_STATIC_ASSERT(is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_traversal::value); # if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) - BOOST_MPL_ASSERT((is_iterator_traversal)); + BOOST_STATIC_ASSERT(is_iterator_traversal::value); # endif }; @@ -158,7 +157,7 @@ struct iterator_category_with_traversal template struct facade_iterator_category_impl { - BOOST_MPL_ASSERT_NOT((is_iterator_category)); + BOOST_STATIC_ASSERT(!is_iterator_category::value); typedef typename iterator_facade_default_category< Traversal,ValueParam,Reference diff --git a/boost/iterator/filter_iterator.hpp b/boost/iterator/filter_iterator.hpp index b87c02b..18c6186 100644 --- a/boost/iterator/filter_iterator.hpp +++ b/boost/iterator/filter_iterator.hpp @@ -12,6 +12,14 @@ #include #include +#include +#include + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) static_cast< _type&& >(_value) +#else +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) _value +#endif namespace boost { namespace iterators { @@ -54,13 +62,13 @@ namespace iterators { filter_iterator() { } filter_iterator(Predicate f, Iterator x, Iterator end_ = Iterator()) - : super_t(x), m_predicate(f), m_end(end_) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f)), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) { satisfy_predicate(); } filter_iterator(Iterator x, Iterator end_ = Iterator()) - : super_t(x), m_predicate(), m_end(end_) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) { // Pro8 is a little too aggressive about instantiating the // body of this function. @@ -111,7 +119,7 @@ namespace iterators { inline filter_iterator make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) { - return filter_iterator(f,x,end); + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f), BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); } template @@ -123,7 +131,7 @@ namespace iterators { >::type x , Iterator end = Iterator()) { - return filter_iterator(x,end); + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); } } // namespace iterators @@ -133,4 +141,6 @@ using iterators::make_filter_iterator; } // namespace boost +#undef BOOST_ITERATOR_DETAIL_MOVE + #endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/boost/iterator/is_iterator.hpp b/boost/iterator/is_iterator.hpp new file mode 100644 index 0000000..5740b19 --- /dev/null +++ b/boost/iterator/is_iterator.hpp @@ -0,0 +1,148 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2023 Andrey Semashev + */ +/*! + * \file iterator/is_iterator.hpp + * + * This header contains definition of the \c is_iterator type trait. + */ + +#ifndef BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ +#define BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS) +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace iterators { +namespace detail { + +// The trait attempts to detect if the T type is an iterator class. Class-type iterators are assumed +// to have the nested type iterator_category. Strictly speaking, this is not required to be the +// case (e.g. a user can specialize iterator_traits for T without defining T::iterator_category). +// Still, this is a good heuristic in practice, and we can't do anything better anyway. +// Since C++17 we can test for iterator_traits::iterator_category presence instead as it is +// required to be only present for iterators. +namespace has_iterator_category_detail { + +typedef char yes_type; +struct no_type { char padding[2]; }; + +template< typename T > +yes_type check( +#if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS) + typename std::iterator_traits< T >::iterator_category* +#else + typename T::iterator_category* +#endif +); +template< typename > +no_type check(...); + +} // namespace has_iterator_category_detail + +template< typename T > +struct is_iterator_impl : + public boost::integral_constant< + bool, + sizeof(has_iterator_category_detail::check< T >(0)) == sizeof(has_iterator_category_detail::yes_type) + > +{ +}; + +template< typename T > +struct is_iterator_impl< T* > : + public boost::conjunction< + boost::is_complete< T >, + boost::negation< boost::is_function< T > > + >::type +{ +}; + +template< typename T, typename U > +struct is_iterator_impl< T U::* > : + public boost::false_type +{ +}; + +template< typename T > +struct is_iterator_impl< T& > : + public boost::false_type +{ +}; + +template< typename T, std::size_t N > +struct is_iterator_impl< T[N] > : + public boost::false_type +{ +}; + +#if !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE) +template< typename T > +struct is_iterator_impl< T[] > : + public boost::false_type +{ +}; + +template< > +struct is_iterator_impl< void > : + public boost::false_type +{ +}; + +template< > +struct is_iterator_impl< void* > : + public boost::false_type +{ +}; +#endif // !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE) + +} // namespace detail + +/*! + * \brief The type trait detects whether the type \c T is an iterator type. + * + * The type trait yields \c true if its argument type \c T, after stripping top level + * cv qualifiers, is one of the following: + * + * - A pointer type, other than a pointer to function, a pointer to a class member, + * or a pointer to an incomplete type, including `void`. + * - A class type for which an iterator category is obtainable. Prior to C++17, + * the iterator category must be defined as a public `T::iterator_category` type. + * Since C++17, the expression `std::iterator_traits< T >::iterator_category` must + * be valid and produce the iterator category type. + * + * Otherwise, the type trait yields \c false. + */ +template< typename T > +struct is_iterator : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< const T > : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< volatile T > : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< const volatile T > : public detail::is_iterator_impl< T >::type {}; + +} // namespace iterators + +using iterators::is_iterator; + +} // namespace boost + +#endif // BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ diff --git a/boost/iterator/iterator_concepts.hpp b/boost/iterator/iterator_concepts.hpp index 415cc49..3c65553 100644 --- a/boost/iterator/iterator_concepts.hpp +++ b/boost/iterator/iterator_concepts.hpp @@ -144,8 +144,8 @@ namespace boost_concepts { typedef typename std::iterator_traits::difference_type difference_type; - BOOST_MPL_ASSERT((boost::is_integral)); - BOOST_MPL_ASSERT_RELATION(std::numeric_limits::is_signed, ==, true); + BOOST_STATIC_ASSERT(boost::is_integral::value); + BOOST_STATIC_ASSERT(std::numeric_limits::is_signed); BOOST_CONCEPT_ASSERT(( boost::Convertible< diff --git a/boost/iterator/minimum_category.hpp b/boost/iterator/minimum_category.hpp deleted file mode 100644 index 15679bc..0000000 --- a/boost/iterator/minimum_category.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright David Abrahams 2003. Use, modification and distribution is -// subject to the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ -# define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ - -# include -# include -# include - -# include -# include - -namespace boost { -namespace iterators { -namespace detail { - -template -struct minimum_category_impl; - -template -struct error_not_related_by_convertibility; - -template <> -struct minimum_category_impl -{ - template struct apply - { - typedef T2 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - { - typedef T1 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - { - BOOST_STATIC_ASSERT((is_same::value)); - typedef T1 type; - }; -}; - -template <> -struct minimum_category_impl -{ - template struct apply - : error_not_related_by_convertibility - { - }; -}; - -} // namespace detail - -// -// Returns the minimum category type or fails to compile -// if T1 and T2 are unrelated. -// -template -struct minimum_category -{ - typedef boost::iterators::detail::minimum_category_impl< - ::boost::is_convertible::value - , ::boost::is_convertible::value - > outer; - - typedef typename outer::template apply inner; - typedef typename inner::type type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) -}; - -template <> -struct minimum_category -{ - template - struct apply : minimum_category - {}; - - BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) -}; - -} // namespace iterators - -} // namespace boost - -#endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ diff --git a/boost/lexical_cast.hpp b/boost/lexical_cast.hpp deleted file mode 100644 index d2838be..0000000 --- a/boost/lexical_cast.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_INCLUDED -#define BOOST_LEXICAL_CAST_INCLUDED - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) -#define BOOST_LCAST_NO_WCHAR_T -#endif - -#include -#include -#include - -namespace boost -{ - template - inline Target lexical_cast(const Source &arg) - { - Target result = Target(); - - if (!boost::conversion::detail::try_lexical_convert(arg, result)) { - boost::conversion::detail::throw_bad_cast(); - } - - return result; - } - - template - inline Target lexical_cast(const char* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } - - template - inline Target lexical_cast(const unsigned char* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } - - template - inline Target lexical_cast(const signed char* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - inline Target lexical_cast(const wchar_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif -#ifndef BOOST_NO_CXX11_CHAR16_T - template - inline Target lexical_cast(const char16_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif -#ifndef BOOST_NO_CXX11_CHAR32_T - template - inline Target lexical_cast(const char32_t* chars, std::size_t count) - { - return ::boost::lexical_cast( - ::boost::iterator_range(chars, chars + count) - ); - } -#endif - -} // namespace boost - -#undef BOOST_LCAST_NO_WCHAR_T - -#endif // BOOST_LEXICAL_CAST_INCLUDED - diff --git a/boost/lexical_cast/bad_lexical_cast.hpp b/boost/lexical_cast/bad_lexical_cast.hpp deleted file mode 100644 index 2dfc77a..0000000 --- a/boost/lexical_cast/bad_lexical_cast.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP -#define BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include -#include - -namespace boost -{ - // exception used to indicate runtime lexical_cast failure - class BOOST_SYMBOL_VISIBLE bad_lexical_cast : - // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0 -#if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS - public std::exception -#else - public std::bad_cast -#endif - -#if defined(BOOST_BORLANDC) && BOOST_WORKAROUND( BOOST_BORLANDC, < 0x560 ) - // under bcc32 5.5.1 bad_cast doesn't derive from exception - , public std::exception -#endif - - { - public: - bad_lexical_cast() BOOST_NOEXCEPT -#ifndef BOOST_NO_TYPEID - : source(&typeid(void)), target(&typeid(void)) -#endif - {} - - const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { - return "bad lexical cast: " - "source type value could not be interpreted as target"; - } - - ~bad_lexical_cast() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE - {} - -#ifndef BOOST_NO_TYPEID - private: -#ifdef BOOST_NO_STD_TYPEINFO - typedef ::type_info type_info_t; -#else - typedef ::std::type_info type_info_t; -#endif - public: - bad_lexical_cast( - const type_info_t &source_type_arg, - const type_info_t &target_type_arg) BOOST_NOEXCEPT - : source(&source_type_arg), target(&target_type_arg) - {} - - const type_info_t &source_type() const BOOST_NOEXCEPT { - return *source; - } - - const type_info_t &target_type() const BOOST_NOEXCEPT { - return *target; - } - - private: - const type_info_t *source; - const type_info_t *target; -#endif - }; - - namespace conversion { namespace detail { -#ifdef BOOST_NO_TYPEID - template - inline void throw_bad_cast() { - boost::throw_exception(bad_lexical_cast()); - } -#else - template - inline void throw_bad_cast() { - boost::throw_exception(bad_lexical_cast(typeid(S), typeid(T))); - } -#endif - }} // namespace conversion::detail - -} // namespace boost - -#endif // BOOST_LEXICAL_CAST_BAD_LEXICAL_CAST_HPP diff --git a/boost/lexical_cast/detail/converter_lexical.hpp b/boost/lexical_cast/detail/converter_lexical.hpp deleted file mode 100644 index 39b2bbf..0000000 --- a/boost/lexical_cast/detail/converter_lexical.hpp +++ /dev/null @@ -1,498 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP -#define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) -#define BOOST_LCAST_NO_WCHAR_T -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef BOOST_NO_CXX11_HDR_ARRAY -#include -#endif - -#include -#include -#include - -#include - -namespace boost { - - namespace detail // normalize_single_byte_char - { - // Converts signed/unsigned char to char - template < class Char > - struct normalize_single_byte_char - { - typedef Char type; - }; - - template <> - struct normalize_single_byte_char< signed char > - { - typedef char type; - }; - - template <> - struct normalize_single_byte_char< unsigned char > - { - typedef char type; - }; - } - - namespace detail // deduce_character_type_later - { - // Helper type, meaning that stram character for T must be deduced - // at Stage 2 (See deduce_source_char and deduce_target_char) - template < class T > struct deduce_character_type_later {}; - } - - namespace detail // stream_char_common - { - // Selectors to choose stream character type (common for Source and Target) - // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later types - // Executed on Stage 1 (See deduce_source_char and deduce_target_char) - template < typename Type > - struct stream_char_common: public boost::conditional< - boost::detail::is_character< Type >::value, - Type, - boost::detail::deduce_character_type_later< Type > - > {}; - - template < typename Char > - struct stream_char_common< Char* >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< Char* > - > {}; - - template < typename Char > - struct stream_char_common< const Char* >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< const Char* > - > {}; - - template < typename Char > - struct stream_char_common< boost::iterator_range< Char* > >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< boost::iterator_range< Char* > > - > {}; - - template < typename Char > - struct stream_char_common< boost::iterator_range< const Char* > >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > > - > {}; - - template < class Char, class Traits, class Alloc > - struct stream_char_common< std::basic_string< Char, Traits, Alloc > > - { - typedef Char type; - }; - - template < class Char, class Traits, class Alloc > - struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > > - { - typedef Char type; - }; - - template < typename Char, std::size_t N > - struct stream_char_common< boost::array< Char, N > >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< boost::array< Char, N > > - > {}; - - template < typename Char, std::size_t N > - struct stream_char_common< boost::array< const Char, N > >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< boost::array< const Char, N > > - > {}; - -#ifndef BOOST_NO_CXX11_HDR_ARRAY - template < typename Char, std::size_t N > - struct stream_char_common< std::array >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< std::array< Char, N > > - > {}; - - template < typename Char, std::size_t N > - struct stream_char_common< std::array< const Char, N > >: public boost::conditional< - boost::detail::is_character< Char >::value, - Char, - boost::detail::deduce_character_type_later< std::array< const Char, N > > - > {}; -#endif - -#ifdef BOOST_HAS_INT128 - template <> struct stream_char_common< boost::int128_type >: public boost::type_identity< char > {}; - template <> struct stream_char_common< boost::uint128_type >: public boost::type_identity< char > {}; -#endif - -#if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T) - template <> - struct stream_char_common< wchar_t > - { - typedef char type; - }; -#endif - } - - namespace detail // deduce_source_char_impl - { - // If type T is `deduce_character_type_later` type, then tries to deduce - // character type using boost::has_left_shift metafunction. - // Otherwise supplied type T is a character type, that must be normalized - // using normalize_single_byte_char. - // Executed at Stage 2 (See deduce_source_char and deduce_target_char) - template < class Char > - struct deduce_source_char_impl - { - typedef BOOST_DEDUCED_TYPENAME boost::detail::normalize_single_byte_char< Char >::type type; - }; - - template < class T > - struct deduce_source_char_impl< deduce_character_type_later< T > > - { - typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t; - -#if defined(BOOST_LCAST_NO_WCHAR_T) - BOOST_STATIC_ASSERT_MSG((result_t::value), - "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation"); - typedef char type; -#else - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - result_t::value, char, wchar_t - >::type type; - - BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value), - "Source type is neither std::ostream`able nor std::wostream`able"); -#endif - }; - } - - namespace detail // deduce_target_char_impl - { - // If type T is `deduce_character_type_later` type, then tries to deduce - // character type using boost::has_right_shift metafunction. - // Otherwise supplied type T is a character type, that must be normalized - // using normalize_single_byte_char. - // Executed at Stage 2 (See deduce_source_char and deduce_target_char) - template < class Char > - struct deduce_target_char_impl - { - typedef BOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type; - }; - - template < class T > - struct deduce_target_char_impl< deduce_character_type_later > - { - typedef boost::has_right_shift, T > result_t; - -#if defined(BOOST_LCAST_NO_WCHAR_T) - BOOST_STATIC_ASSERT_MSG((result_t::value), - "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation"); - typedef char type; -#else - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - result_t::value, char, wchar_t - >::type type; - - BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift, T >::value), - "Target type is neither std::istream`able nor std::wistream`able"); -#endif - }; - } - - namespace detail // deduce_target_char and deduce_source_char - { - // We deduce stream character types in two stages. - // - // Stage 1 is common for Target and Source. At Stage 1 we get - // non normalized character type (may contain unsigned/signed char) - // or deduce_character_type_later where T is the original type. - // Stage 1 is executed by stream_char_common - // - // At Stage 2 we normalize character types or try to deduce character - // type using metafunctions. - // Stage 2 is executed by deduce_target_char_impl and - // deduce_source_char_impl - // - // deduce_target_char and deduce_source_char functions combine - // both stages - - template < class T > - struct deduce_target_char - { - typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type; - typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type; - - typedef stage2_type type; - }; - - template < class T > - struct deduce_source_char - { - typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type; - typedef BOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type; - - typedef stage2_type type; - }; - } - - namespace detail // extract_char_traits template - { - // We are attempting to get char_traits<> from T - // template parameter. Otherwise we'll be using std::char_traits - template < class Char, class T > - struct extract_char_traits - : boost::false_type - { - typedef std::char_traits< Char > trait_t; - }; - - template < class Char, class Traits, class Alloc > - struct extract_char_traits< Char, std::basic_string< Char, Traits, Alloc > > - : boost::true_type - { - typedef Traits trait_t; - }; - - template < class Char, class Traits, class Alloc> - struct extract_char_traits< Char, boost::container::basic_string< Char, Traits, Alloc > > - : boost::true_type - { - typedef Traits trait_t; - }; - } - - namespace detail // array_to_pointer_decay - { - template - struct array_to_pointer_decay - { - typedef T type; - }; - - template - struct array_to_pointer_decay - { - typedef const T * type; - }; - } - - namespace detail // lcast_src_length - { - // Return max. length of string representation of Source; - template< class Source, // Source type of lexical_cast. - class Enable = void // helper type - > - struct lcast_src_length - { - BOOST_STATIC_CONSTANT(std::size_t, value = 1); - }; - - // Helper for integral types. - // Notes on length calculation: - // Max length for 32bit int with grouping "\1" and thousands_sep ',': - // "-2,1,4,7,4,8,3,6,4,7" - // ^ - is_signed - // ^ - 1 digit not counted by digits10 - // ^^^^^^^^^^^^^^^^^^ - digits10 * 2 - // - // Constant is_specialized is used instead of constant 1 - // to prevent buffer overflow in a rare case when - // doesn't add missing specialization for - // numeric_limits for some integral type T. - // When is_specialized is false, the whole expression is 0. - template - struct lcast_src_length< - Source, BOOST_DEDUCED_TYPENAME boost::enable_if >::type - > - { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_CONSTANT(std::size_t, value = - std::numeric_limits::is_signed + - std::numeric_limits::is_specialized + /* == 1 */ - std::numeric_limits::digits10 * 2 - ); -#else - BOOST_STATIC_CONSTANT(std::size_t, value = 156); - BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256); -#endif - }; - - // Helper for floating point types. - // -1.23456789e-123456 - // ^ sign - // ^ leading digit - // ^ decimal point - // ^^^^^^^^ lcast_precision::value - // ^ "e" - // ^ exponent sign - // ^^^^^^ exponent (assumed 6 or less digits) - // sign + leading digit + decimal point + "e" + exponent sign == 5 - template - struct lcast_src_length< - Source, BOOST_DEDUCED_TYPENAME boost::enable_if >::type - > - { - -#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - BOOST_STATIC_ASSERT( - std::numeric_limits::max_exponent10 <= 999999L && - std::numeric_limits::min_exponent10 >= -999999L - ); - - BOOST_STATIC_CONSTANT(std::size_t, value = - 5 + lcast_precision::value + 6 - ); -#else // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - BOOST_STATIC_CONSTANT(std::size_t, value = 156); -#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION - }; - } - - namespace detail // lexical_cast_stream_traits - { - template - struct lexical_cast_stream_traits { - typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cv_src; - - typedef boost::detail::deduce_source_char deduce_src_char_metafunc; - typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t; - typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char::type target_char_t; - - typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char< - target_char_t, src_char_t - >::type char_type; - -#if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value - && !boost::is_same::value), - "Your compiler does not have full support for char16_t" ); -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS) - BOOST_STATIC_ASSERT_MSG(( !boost::is_same::value - && !boost::is_same::value), - "Your compiler does not have full support for char32_t" ); -#endif - - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::detail::extract_char_traits::value, - BOOST_DEDUCED_TYPENAME boost::detail::extract_char_traits, - BOOST_DEDUCED_TYPENAME boost::detail::extract_char_traits - >::type::trait_t traits; - - typedef boost::integral_constant< - bool, - boost::is_same::value && // source is not a wide character based type - (sizeof(char) != sizeof(target_char_t)) && // target type is based on wide character - (!(boost::detail::is_character::value)) - > is_string_widening_required_t; - - typedef boost::integral_constant< - bool, - !(boost::is_integral::value || - boost::detail::is_character< - BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1 - >::value // then we have no optimization for that type - ) - > is_source_input_not_optimized_t; - - // If we have an optimized conversion for - // Source, we do not need to construct stringbuf. - BOOST_STATIC_CONSTANT(bool, requires_stringbuf = - (is_string_widening_required_t::value || is_source_input_not_optimized_t::value) - ); - - typedef boost::detail::lcast_src_length len_t; - }; - } - - namespace detail - { - template - struct lexical_converter_impl - { - typedef lexical_cast_stream_traits stream_trait; - - typedef detail::lexical_istream_limited_src< - BOOST_DEDUCED_TYPENAME stream_trait::char_type, - BOOST_DEDUCED_TYPENAME stream_trait::traits, - stream_trait::requires_stringbuf, - stream_trait::len_t::value + 1 - > i_interpreter_type; - - typedef detail::lexical_ostream_limited_src< - BOOST_DEDUCED_TYPENAME stream_trait::char_type, - BOOST_DEDUCED_TYPENAME stream_trait::traits - > o_interpreter_type; - - static inline bool try_convert(const Source& arg, Target& result) { - i_interpreter_type i_interpreter; - - // Disabling ADL, by directly specifying operators. - if (!(i_interpreter.operator <<(arg))) - return false; - - o_interpreter_type out(i_interpreter.cbegin(), i_interpreter.cend()); - - // Disabling ADL, by directly specifying operators. - if(!(out.operator >>(result))) - return false; - - return true; - } - }; - } - -} // namespace boost - -#undef BOOST_LCAST_NO_WCHAR_T - -#endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP - diff --git a/boost/lexical_cast/detail/converter_lexical_streams.hpp b/boost/lexical_cast/detail/converter_lexical_streams.hpp deleted file mode 100644 index 04383bf..0000000 --- a/boost/lexical_cast/detail/converter_lexical_streams.hpp +++ /dev/null @@ -1,775 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014, Nowember 2016 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP -#define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - - -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) -#define BOOST_LCAST_NO_WCHAR_T -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef BOOST_NO_STD_LOCALE -# include -#else -# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // Getting error at this point means, that your STL library is old/lame/misconfigured. - // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE, - // but beware: lexical_cast will understand only 'C' locale delimeters and thousands - // separators. -# error "Unable to use header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force " -# error "boost::lexical_cast to use only 'C' locale during conversions." -# endif -#endif - -#ifdef BOOST_NO_STRINGSTREAM -#include -#else -#include -#endif - -#include -#include -#include - -#include - -#ifndef BOOST_NO_CXX11_HDR_ARRAY -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BOOST_NO_CWCHAR -# include -#endif - -namespace boost { - - namespace detail // basic_unlockedbuf - { - // acts as a stream buffer which wraps around a pair of pointers - // and gives acces to internals - template - class basic_unlockedbuf : public basic_pointerbuf { - public: - typedef basic_pointerbuf base_type; - typedef BOOST_DEDUCED_TYPENAME base_type::streamsize streamsize; - -#ifndef BOOST_NO_USING_TEMPLATE - using base_type::pptr; - using base_type::pbase; - using base_type::setbuf; -#else - charT* pptr() const { return base_type::pptr(); } - charT* pbase() const { return base_type::pbase(); } - BufferType* setbuf(char_type* s, streamsize n) { return base_type::setbuf(s, n); } -#endif - }; - } - - namespace detail - { - struct do_not_construct_out_buffer_t{}; - struct do_not_construct_out_stream_t{ - do_not_construct_out_stream_t(do_not_construct_out_buffer_t*){} - }; - - template - struct out_stream_helper_trait { -#if defined(BOOST_NO_STRINGSTREAM) - typedef std::ostream out_stream_t; - typedef basic_unlockedbuf stringbuffer_t; -#elif defined(BOOST_NO_STD_LOCALE) - typedef std::ostream out_stream_t; - typedef basic_unlockedbuf stringbuffer_t; - typedef basic_unlockedbuf buffer_t; -#else - typedef std::basic_ostream out_stream_t; - typedef basic_unlockedbuf, CharT> stringbuffer_t; - typedef basic_unlockedbuf, CharT> buffer_t; -#endif - }; - } - - namespace detail // optimized stream wrappers - { - template< class CharT // a result of widest_char transformation - , class Traits - , bool RequiresStringbuffer - , std::size_t CharacterBufferSize - > - class lexical_istream_limited_src: boost::noncopyable { - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - RequiresStringbuffer, - BOOST_DEDUCED_TYPENAME out_stream_helper_trait::out_stream_t, - do_not_construct_out_stream_t - >::type deduced_out_stream_t; - - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - RequiresStringbuffer, - BOOST_DEDUCED_TYPENAME out_stream_helper_trait::stringbuffer_t, - do_not_construct_out_buffer_t - >::type deduced_out_buffer_t; - - deduced_out_buffer_t out_buffer; - deduced_out_stream_t out_stream; - CharT buffer[CharacterBufferSize]; - - // After the `operator <<` finishes, `[start, finish)` is - // the range to output by `operator >>` - const CharT* start; - const CharT* finish; - - public: - lexical_istream_limited_src() BOOST_NOEXCEPT - : out_buffer() - , out_stream(&out_buffer) - , start(buffer) - , finish(buffer + CharacterBufferSize) - {} - - const CharT* cbegin() const BOOST_NOEXCEPT { - return start; - } - - const CharT* cend() const BOOST_NOEXCEPT { - return finish; - } - - private: -/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/ - bool shl_char(CharT ch) BOOST_NOEXCEPT { - Traits::assign(buffer[0], ch); - finish = start + 1; - return true; - } - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - bool shl_char(T ch) { - BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) , - "boost::lexical_cast does not support narrowing of char types." - "Use boost::locale instead" ); -#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - std::locale loc; - CharT const w = BOOST_USE_FACET(std::ctype, loc).widen(ch); -#else - CharT const w = static_cast(ch); -#endif - Traits::assign(buffer[0], w); - finish = start + 1; - return true; - } -#endif - - bool shl_char_array(CharT const* str_value) BOOST_NOEXCEPT { - start = str_value; - finish = start + Traits::length(str_value); - return true; - } - - template - bool shl_char_array(T const* str_value) { - BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)), - "boost::lexical_cast does not support narrowing of char types." - "Use boost::locale instead" ); - return shl_input_streamable(str_value); - } - - bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT { - start = str; - finish = std::find(start, start + max_size, Traits::to_char_type(0)); - return true; - } - - template - bool shl_input_streamable(InputStreamable& input) { -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) - // If you have compilation error at this point, than your STL library - // does not support such conversions. Try updating it. - BOOST_STATIC_ASSERT((boost::is_same::value)); -#endif - -#ifndef BOOST_NO_EXCEPTIONS - out_stream.exceptions(std::ios::badbit); - try { -#endif - bool const result = !(out_stream << input).fail(); - const deduced_out_buffer_t* const p = static_cast( - out_stream.rdbuf() - ); - start = p->pbase(); - finish = p->pptr(); - return result; -#ifndef BOOST_NO_EXCEPTIONS - } catch (const ::std::ios_base::failure& /*f*/) { - return false; - } -#endif - } - - template - inline bool shl_unsigned(const T n) { - CharT* tmp_finish = buffer + CharacterBufferSize; - start = lcast_put_unsigned(n, tmp_finish).convert(); - finish = tmp_finish; - return true; - } - - template - inline bool shl_signed(const T n) { - CharT* tmp_finish = buffer + CharacterBufferSize; - typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned::type utype; - CharT* tmp_start = lcast_put_unsigned(lcast_to_unsigned(n), tmp_finish).convert(); - if (n < 0) { - --tmp_start; - CharT const minus = lcast_char_constants::minus; - Traits::assign(*tmp_start, minus); - } - start = tmp_start; - finish = tmp_finish; - return true; - } - - template - bool shl_real_type(const T& val, SomeCharT* /*begin*/) { - lcast_set_precision(out_stream, &val); - return shl_input_streamable(val); - } - - bool shl_real_type(float val, char* begin) { - using namespace std; - const double val_as_double = val; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*g", static_cast(boost::detail::lcast_get_precision()), val_as_double); - return finish > start; - } - - bool shl_real_type(double val, char* begin) { - using namespace std; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*g", static_cast(boost::detail::lcast_get_precision()), val); - return finish > start; - } - -#ifndef __MINGW32__ - bool shl_real_type(long double val, char* begin) { - using namespace std; - finish = start + - boost::core::snprintf(begin, CharacterBufferSize, - "%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; - } -#endif - - -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__) - bool shl_real_type(float val, wchar_t* begin) { - using namespace std; - const double val_as_double = val; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*g", - static_cast(boost::detail::lcast_get_precision()), - val_as_double ); - return finish > start; - } - - bool shl_real_type(double val, wchar_t* begin) { - using namespace std; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*g", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; - } - - bool shl_real_type(long double val, wchar_t* begin) { - using namespace std; - finish = start + swprintf(begin, CharacterBufferSize, - L"%.*Lg", static_cast(boost::detail::lcast_get_precision()), val ); - return finish > start; - } -#endif - template - bool shl_real(T val) { - CharT* tmp_finish = buffer + CharacterBufferSize; - if (put_inf_nan(buffer, tmp_finish, val)) { - finish = tmp_finish; - return true; - } - - return shl_real_type(val, static_cast(buffer)); - } - -/************************************ OPERATORS << ( ... ) ********************************/ - public: - template - bool operator<<(std::basic_string const& str) BOOST_NOEXCEPT { - start = str.data(); - finish = start + str.length(); - return true; - } - - template - bool operator<<(boost::container::basic_string const& str) BOOST_NOEXCEPT { - start = str.data(); - finish = start + str.length(); - return true; - } - - bool operator<<(bool value) BOOST_NOEXCEPT { - CharT const czero = lcast_char_constants::zero; - Traits::assign(buffer[0], Traits::to_char_type(czero + value)); - finish = start + 1; - return true; - } - - template - BOOST_DEDUCED_TYPENAME boost::disable_if, bool>::type - operator<<(const iterator_range& rng) BOOST_NOEXCEPT { - return (*this) << iterator_range(rng.begin(), rng.end()); - } - - bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { - start = rng.begin(); - finish = rng.end(); - return true; - } - - bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { - return (*this) << iterator_range( - reinterpret_cast(rng.begin()), - reinterpret_cast(rng.end()) - ); - } - - bool operator<<(const iterator_range& rng) BOOST_NOEXCEPT { - return (*this) << iterator_range( - reinterpret_cast(rng.begin()), - reinterpret_cast(rng.end()) - ); - } - - bool operator<<(char ch) { return shl_char(ch); } - bool operator<<(unsigned char ch) { return ((*this) << static_cast(ch)); } - bool operator<<(signed char ch) { return ((*this) << static_cast(ch)); } -#if !defined(BOOST_LCAST_NO_WCHAR_T) - bool operator<<(wchar_t const* str) { return shl_char_array(str); } - bool operator<<(wchar_t * str) { return shl_char_array(str); } -#ifndef BOOST_NO_INTRINSIC_WCHAR_T - bool operator<<(wchar_t ch) { return shl_char(ch); } -#endif -#endif -#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator<<(char16_t ch) { return shl_char(ch); } - bool operator<<(char16_t * str) { return shl_char_array(str); } - bool operator<<(char16_t const * str) { return shl_char_array(str); } -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator<<(char32_t ch) { return shl_char(ch); } - bool operator<<(char32_t * str) { return shl_char_array(str); } - bool operator<<(char32_t const * str) { return shl_char_array(str); } -#endif - bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast(ch)); } - bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast(ch)); } - bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast(ch)); } - bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast(ch)); } - bool operator<<(char const* str_value) { return shl_char_array(str_value); } - bool operator<<(char* str_value) { return shl_char_array(str_value); } - bool operator<<(short n) { return shl_signed(n); } - bool operator<<(int n) { return shl_signed(n); } - bool operator<<(long n) { return shl_signed(n); } - bool operator<<(unsigned short n) { return shl_unsigned(n); } - bool operator<<(unsigned int n) { return shl_unsigned(n); } - bool operator<<(unsigned long n) { return shl_unsigned(n); } - -#if defined(BOOST_HAS_LONG_LONG) - bool operator<<(boost::ulong_long_type n) { return shl_unsigned(n); } - bool operator<<(boost::long_long_type n) { return shl_signed(n); } -#elif defined(BOOST_HAS_MS_INT64) - bool operator<<(unsigned __int64 n) { return shl_unsigned(n); } - bool operator<<( __int64 n) { return shl_signed(n); } -#endif - -#ifdef BOOST_HAS_INT128 - bool operator<<(const boost::uint128_type& n) { return shl_unsigned(n); } - bool operator<<(const boost::int128_type& n) { return shl_signed(n); } -#endif - bool operator<<(float val) { return shl_real(val); } - bool operator<<(double val) { return shl_real(val); } - bool operator<<(long double val) { -#ifndef __MINGW32__ - return shl_real(val); -#else - return shl_real(static_cast(val)); -#endif - } - - // Adding constness to characters. Constness does not change layout - template - BOOST_DEDUCED_TYPENAME boost::disable_if, bool>::type - operator<<(boost::array const& input) BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG( - (sizeof(boost::array) == sizeof(boost::array)), - "boost::array and boost::array must have exactly the same layout." - ); - return ((*this) << reinterpret_cast const& >(input)); - } - - template - bool operator<<(boost::array const& input) BOOST_NOEXCEPT { - return shl_char_array_limited(input.data(), N); - } - - template - bool operator<<(boost::array const& input) BOOST_NOEXCEPT { - return ((*this) << reinterpret_cast const& >(input)); - } - - template - bool operator<<(boost::array const& input) BOOST_NOEXCEPT { - return ((*this) << reinterpret_cast const& >(input)); - } - -#ifndef BOOST_NO_CXX11_HDR_ARRAY - // Making a Boost.Array from std::array - template - bool operator<<(std::array const& input) BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG( - (sizeof(std::array) == sizeof(boost::array)), - "std::array and boost::array must have exactly the same layout. " - "Bug in implementation of std::array or boost::array." - ); - return ((*this) << reinterpret_cast const& >(input)); - } -#endif - template - bool operator<<(const InStreamable& input) { return shl_input_streamable(input); } - }; - - - template - class lexical_ostream_limited_src: boost::noncopyable { - //`[start, finish)` is the range to output by `operator >>` - const CharT* start; - const CharT* const finish; - - public: - lexical_ostream_limited_src(const CharT* begin, const CharT* end) BOOST_NOEXCEPT - : start(begin) - , finish(end) - {} - -/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/ - private: - template - bool shr_unsigned(Type& output) { - if (start == finish) return false; - CharT const minus = lcast_char_constants::minus; - CharT const plus = lcast_char_constants::plus; - bool const has_minus = Traits::eq(minus, *start); - - /* We won`t use `start' any more, so no need in decrementing it after */ - if (has_minus || Traits::eq(plus, *start)) { - ++start; - } - - bool const succeed = lcast_ret_unsigned(output, start, finish).convert(); - - if (has_minus) { - output = static_cast(0u - output); - } - - return succeed; - } - - template - bool shr_signed(Type& output) { - if (start == finish) return false; - CharT const minus = lcast_char_constants::minus; - CharT const plus = lcast_char_constants::plus; - typedef BOOST_DEDUCED_TYPENAME make_unsigned::type utype; - utype out_tmp = 0; - bool const has_minus = Traits::eq(minus, *start); - - /* We won`t use `start' any more, so no need in decrementing it after */ - if (has_minus || Traits::eq(plus, *start)) { - ++start; - } - - bool succeed = lcast_ret_unsigned(out_tmp, start, finish).convert(); - if (has_minus) { - utype const comp_val = (static_cast(1) << std::numeric_limits::digits); - succeed = succeed && out_tmp<=comp_val; - output = static_cast(0u - out_tmp); - } else { - utype const comp_val = static_cast((std::numeric_limits::max)()); - succeed = succeed && out_tmp<=comp_val; - output = static_cast(out_tmp); - } - return succeed; - } - - template - bool shr_using_base_class(InputStreamable& output) - { - BOOST_STATIC_ASSERT_MSG( - (!boost::is_pointer::value), - "boost::lexical_cast can not convert to pointers" - ); - -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) - BOOST_STATIC_ASSERT_MSG((boost::is_same::value), - "boost::lexical_cast can not convert, because your STL library does not " - "support such conversions. Try updating it." - ); -#endif - -#if defined(BOOST_NO_STRINGSTREAM) - std::istrstream stream(start, static_cast(finish - start)); -#else - typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait::buffer_t buffer_t; - buffer_t buf; - // Usually `istream` and `basic_istream` do not modify - // content of buffer; `buffer_t` assures that this is true - buf.setbuf(const_cast(start), static_cast(finish - start)); -#if defined(BOOST_NO_STD_LOCALE) - std::istream stream(&buf); -#else - std::basic_istream stream(&buf); -#endif // BOOST_NO_STD_LOCALE -#endif // BOOST_NO_STRINGSTREAM - -#ifndef BOOST_NO_EXCEPTIONS - stream.exceptions(std::ios::badbit); - try { -#endif - stream.unsetf(std::ios::skipws); - lcast_set_precision(stream, static_cast(0)); - - return (stream >> output) - && (stream.get() == Traits::eof()); - -#ifndef BOOST_NO_EXCEPTIONS - } catch (const ::std::ios_base::failure& /*f*/) { - return false; - } -#endif - } - - template - inline bool shr_xchar(T& output) BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ), - "boost::lexical_cast does not support narrowing of character types." - "Use boost::locale instead" ); - bool const ok = (finish - start == 1); - if (ok) { - CharT out; - Traits::assign(out, *start); - output = static_cast(out); - } - return ok; - } - - template - bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT { - using namespace std; - const std::size_t size = static_cast(finish - start); - if (size > N - 1) { // `-1` because we need to store \0 at the end - return false; - } - - memcpy(&output[0], start, size * sizeof(CharT)); - output[size] = Traits::to_char_type(0); - return true; - } - -/************************************ OPERATORS >> ( ... ) ********************************/ - public: - bool operator>>(unsigned short& output) { return shr_unsigned(output); } - bool operator>>(unsigned int& output) { return shr_unsigned(output); } - bool operator>>(unsigned long int& output) { return shr_unsigned(output); } - bool operator>>(short& output) { return shr_signed(output); } - bool operator>>(int& output) { return shr_signed(output); } - bool operator>>(long int& output) { return shr_signed(output); } -#if defined(BOOST_HAS_LONG_LONG) - bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); } - bool operator>>(boost::long_long_type& output) { return shr_signed(output); } -#elif defined(BOOST_HAS_MS_INT64) - bool operator>>(unsigned __int64& output) { return shr_unsigned(output); } - bool operator>>(__int64& output) { return shr_signed(output); } -#endif - -#ifdef BOOST_HAS_INT128 - bool operator>>(boost::uint128_type& output) { return shr_unsigned(output); } - bool operator>>(boost::int128_type& output) { return shr_signed(output); } -#endif - - bool operator>>(char& output) { return shr_xchar(output); } - bool operator>>(unsigned char& output) { return shr_xchar(output); } - bool operator>>(signed char& output) { return shr_xchar(output); } -#if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) - bool operator>>(wchar_t& output) { return shr_xchar(output); } -#endif -#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator>>(char16_t& output) { return shr_xchar(output); } -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - bool operator>>(char32_t& output) { return shr_xchar(output); } -#endif - template - bool operator>>(std::basic_string& str) { - str.assign(start, finish); return true; - } - - template - bool operator>>(boost::container::basic_string& str) { - str.assign(start, finish); return true; - } - - template - bool operator>>(boost::array& output) BOOST_NOEXCEPT { - return shr_std_array(output); - } - - template - bool operator>>(boost::array& output) BOOST_NOEXCEPT { - return ((*this) >> reinterpret_cast& >(output)); - } - - template - bool operator>>(boost::array& output) BOOST_NOEXCEPT { - return ((*this) >> reinterpret_cast& >(output)); - } - -#ifndef BOOST_NO_CXX11_HDR_ARRAY - template - bool operator>>(std::array& output) BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG( - (sizeof(std::array) == sizeof(boost::array)), - "std::array and boost::array must have exactly the same layout." - ); - return ((*this) >> reinterpret_cast& >(output)); - } -#endif - - bool operator>>(bool& output) BOOST_NOEXCEPT { - output = false; // Suppress warning about uninitalized variable - - if (start == finish) return false; - CharT const zero = lcast_char_constants::zero; - CharT const plus = lcast_char_constants::plus; - CharT const minus = lcast_char_constants::minus; - - const CharT* const dec_finish = finish - 1; - output = Traits::eq(*dec_finish, zero + 1); - if (!output && !Traits::eq(*dec_finish, zero)) { - return false; // Does not ends on '0' or '1' - } - - if (start == dec_finish) return true; - - // We may have sign at the beginning - if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) { - ++ start; - } - - // Skipping zeros - while (start != dec_finish) { - if (!Traits::eq(zero, *start)) { - return false; // Not a zero => error - } - - ++ start; - } - - return true; - } - - private: - // Not optimised converter - template - bool float_types_converter_internal(T& output) { - if (parse_inf_nan(start, finish, output)) return true; - bool const return_value = shr_using_base_class(output); - - /* Some compilers and libraries successfully - * parse 'inf', 'INFINITY', '1.0E', '1.0E-'... - * We are trying to provide a unified behaviour, - * so we just forbid such conversions (as some - * of the most popular compilers/libraries do) - * */ - CharT const minus = lcast_char_constants::minus; - CharT const plus = lcast_char_constants::plus; - CharT const capital_e = lcast_char_constants::capital_e; - CharT const lowercase_e = lcast_char_constants::lowercase_e; - if ( return_value && - ( - Traits::eq(*(finish-1), lowercase_e) // 1.0e - || Traits::eq(*(finish-1), capital_e) // 1.0E - || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E- - || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+ - ) - ) return false; - - return return_value; - } - - public: - bool operator>>(float& output) { return float_types_converter_internal(output); } - bool operator>>(double& output) { return float_types_converter_internal(output); } - bool operator>>(long double& output) { return float_types_converter_internal(output); } - - // Generic istream-based algorithm. - // lcast_streambuf_for_target::value is true. - template - bool operator>>(InputStreamable& output) { - return shr_using_base_class(output); - } - }; - } -} // namespace boost - -#undef BOOST_LCAST_NO_WCHAR_T - -#endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP - diff --git a/boost/lexical_cast/detail/converter_numeric.hpp b/boost/lexical_cast/detail/converter_numeric.hpp deleted file mode 100644 index 853e254..0000000 --- a/boost/lexical_cast/detail/converter_numeric.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2016 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP -#define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace detail { - -template -struct detect_precision_loss -{ - typedef Source source_type; - typedef boost::numeric::Trunc Rounder; - typedef BOOST_DEDUCED_TYPENAME conditional< - boost::is_arithmetic::value, Source, Source const& - >::type argument_type ; - - static inline source_type nearbyint(argument_type s, bool& is_ok) BOOST_NOEXCEPT { - const source_type near_int = Rounder::nearbyint(s); - if (near_int && is_ok) { - const source_type orig_div_round = s / near_int; - const source_type eps = std::numeric_limits::epsilon(); - - is_ok = !((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps); - } - - return s; - } - - typedef typename Rounder::round_style round_style; -}; - -template -struct fake_precision_loss: public Base -{ - typedef Source source_type ; - typedef BOOST_DEDUCED_TYPENAME conditional< - boost::is_arithmetic::value, Source, Source const& - >::type argument_type ; - - static inline source_type nearbyint(argument_type s, bool& /*is_ok*/) BOOST_NOEXCEPT { - return s; - } -}; - -struct nothrow_overflow_handler -{ - inline bool operator() ( boost::numeric::range_check_result r ) const BOOST_NOEXCEPT { - return (r == boost::numeric::cInRange); - } -}; - -template -inline bool noexcept_numeric_convert(const Source& arg, Target& result) BOOST_NOEXCEPT { - typedef boost::numeric::converter< - Target, - Source, - boost::numeric::conversion_traits, - nothrow_overflow_handler, - detect_precision_loss - > converter_orig_t; - - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_base_of< detect_precision_loss, converter_orig_t >::value, - converter_orig_t, - fake_precision_loss - >::type converter_t; - - bool res = nothrow_overflow_handler()(converter_t::out_of_range(arg)); - if (res) { - result = converter_t::low_level_convert(converter_t::nearbyint(arg, res)); - } - - return res; -} - -template -struct lexical_cast_dynamic_num_not_ignoring_minus -{ - static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT { - return noexcept_numeric_convert(arg, result); - } -}; - -template -struct lexical_cast_dynamic_num_ignoring_minus -{ - static inline bool try_convert(const Source &arg, Target& result) BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_float::value, - boost::type_identity, - boost::make_unsigned - >::type usource_lazy_t; - typedef BOOST_DEDUCED_TYPENAME usource_lazy_t::type usource_t; - - if (arg < 0) { - const bool res = noexcept_numeric_convert(0u - arg, result); - result = static_cast(0u - result); - return res; - } else { - return noexcept_numeric_convert(arg, result); - } - } -}; - -/* - * lexical_cast_dynamic_num follows the rules: - * 1) If Source can be converted to Target without precision loss and - * without overflows, then assign Source to Target and return - * - * 2) If Source is less than 0 and Target is an unsigned integer, - * then negate Source, check the requirements of rule 1) and if - * successful, assign static_casted Source to Target and return - * - * 3) Otherwise throw a bad_lexical_cast exception - * - * - * Rule 2) required because boost::lexical_cast has the behavior of - * stringstream, which uses the rules of scanf for conversions. And - * in the C99 standard for unsigned input value minus sign is - * optional, so if a negative number is read, no errors will arise - * and the result will be the two's complement. - */ -template -struct dynamic_num_converter_impl -{ - typedef BOOST_DEDUCED_TYPENAME boost::remove_volatile::type source_type; - - static inline bool try_convert(source_type arg, Target& result) BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_unsigned::value && - (boost::is_signed::value || boost::is_float::value) && - !(boost::is_same::value) && - !(boost::is_same::value), - lexical_cast_dynamic_num_ignoring_minus, - lexical_cast_dynamic_num_not_ignoring_minus - >::type caster_type; - - return caster_type::try_convert(arg, result); - } -}; - -}} // namespace boost::detail - -#endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_NUMERIC_HPP - diff --git a/boost/lexical_cast/detail/inf_nan.hpp b/boost/lexical_cast/detail/inf_nan.hpp deleted file mode 100644 index ef53e52..0000000 --- a/boost/lexical_cast/detail/inf_nan.hpp +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP -#define BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING) -#define BOOST_LCAST_NO_WCHAR_T -#endif - -#include -#include -#include -#include -#include - -#include - -namespace boost { - namespace detail - { - template - bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT { - for( unsigned int i=0; i < len; ++i ) { - if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false; - } - - return true; - } - - /* Returns true and sets the correct value if found NaN or Inf. */ - template - inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value - , const CharT* lc_NAN, const CharT* lc_nan - , const CharT* lc_INFINITY, const CharT* lc_infinity - , const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT - { - if (begin == end) return false; - const CharT minus = lcast_char_constants::minus; - const CharT plus = lcast_char_constants::plus; - const int inifinity_size = 8; // == sizeof("infinity") - 1 - - /* Parsing +/- */ - bool const has_minus = (*begin == minus); - if (has_minus || *begin == plus) { - ++ begin; - } - - if (end - begin < 3) return false; - if (lc_iequal(begin, lc_nan, lc_NAN, 3)) { - begin += 3; - if (end != begin) { - /* It is 'nan(...)' or some bad input*/ - - if (end - begin < 2) return false; // bad input - -- end; - if (*begin != opening_brace || *end != closing_brace) return false; // bad input - } - - if( !has_minus ) value = std::numeric_limits::quiet_NaN(); - else value = boost::core::copysign(std::numeric_limits::quiet_NaN(), static_cast(-1)); - return true; - } else if ( - ( /* 'INF' or 'inf' */ - end - begin == 3 // 3 == sizeof('inf') - 1 - && lc_iequal(begin, lc_infinity, lc_INFINITY, 3) - ) - || - ( /* 'INFINITY' or 'infinity' */ - end - begin == inifinity_size - && lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size) - ) - ) - { - if( !has_minus ) value = std::numeric_limits::infinity(); - else value = -std::numeric_limits::infinity(); - return true; - } - - return false; - } - - template - bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value - , const CharT* lc_nan - , const CharT* lc_infinity) BOOST_NOEXCEPT - { - const CharT minus = lcast_char_constants::minus; - if (boost::core::isnan(value)) { - if (boost::core::signbit(value)) { - *begin = minus; - ++ begin; - } - - std::memcpy(begin, lc_nan, 3 * sizeof(CharT)); - end = begin + 3; - return true; - } else if (boost::core::isinf(value)) { - if (boost::core::signbit(value)) { - *begin = minus; - ++ begin; - } - - std::memcpy(begin, lc_infinity, 3 * sizeof(CharT)); - end = begin + 3; - return true; - } - - return false; - } - - -#ifndef BOOST_LCAST_NO_WCHAR_T - template - bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT { - return parse_inf_nan_impl(begin, end, value - , L"NAN", L"nan" - , L"INFINITY", L"infinity" - , L'(', L')'); - } - - template - bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT { - return put_inf_nan_impl(begin, end, value, L"nan", L"infinity"); - } - -#endif -#if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - template - bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT { - return parse_inf_nan_impl(begin, end, value - , u"NAN", u"nan" - , u"INFINITY", u"infinity" - , u'(', u')'); - } - - template - bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT { - return put_inf_nan_impl(begin, end, value, u"nan", u"infinity"); - } -#endif -#if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS) - template - bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT { - return parse_inf_nan_impl(begin, end, value - , U"NAN", U"nan" - , U"INFINITY", U"infinity" - , U'(', U')'); - } - - template - bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT { - return put_inf_nan_impl(begin, end, value, U"nan", U"infinity"); - } -#endif - - template - bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT { - return parse_inf_nan_impl(begin, end, value - , "NAN", "nan" - , "INFINITY", "infinity" - , '(', ')'); - } - - template - bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT { - return put_inf_nan_impl(begin, end, value, "nan", "infinity"); - } - } -} // namespace boost - -#undef BOOST_LCAST_NO_WCHAR_T - -#endif // BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP - diff --git a/boost/lexical_cast/detail/is_character.hpp b/boost/lexical_cast/detail/is_character.hpp deleted file mode 100644 index 176dd3d..0000000 --- a/boost/lexical_cast/detail/is_character.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP -#define BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include - -namespace boost { - - namespace detail // is_character<...> - { - // returns true, if T is one of the character types - template < typename T > - struct is_character - { - typedef BOOST_DEDUCED_TYPENAME boost::integral_constant< - bool, - boost::is_same< T, char >::value || - #if !defined(BOOST_NO_STRINGSTREAM) && !defined(BOOST_NO_STD_WSTRING) - boost::is_same< T, wchar_t >::value || - #endif - #ifndef BOOST_NO_CXX11_CHAR16_T - boost::is_same< T, char16_t >::value || - #endif - #ifndef BOOST_NO_CXX11_CHAR32_T - boost::is_same< T, char32_t >::value || - #endif - boost::is_same< T, unsigned char >::value || - boost::is_same< T, signed char >::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = (type::value) ); - }; - } -} - -#endif // BOOST_LEXICAL_CAST_DETAIL_IS_CHARACTER_HPP - diff --git a/boost/lexical_cast/detail/lcast_char_constants.hpp b/boost/lexical_cast/detail/lcast_char_constants.hpp deleted file mode 100644 index e2069a5..0000000 --- a/boost/lexical_cast/detail/lcast_char_constants.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP -#define BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost -{ - namespace detail // '0', '-', '+', 'e', 'E' and '.' constants - { - template < typename Char > - struct lcast_char_constants { - // We check in tests assumption that static casted character is - // equal to correctly written C++ literal: U'0' == static_cast('0') - BOOST_STATIC_CONSTANT(Char, zero = static_cast('0')); - BOOST_STATIC_CONSTANT(Char, minus = static_cast('-')); - BOOST_STATIC_CONSTANT(Char, plus = static_cast('+')); - BOOST_STATIC_CONSTANT(Char, lowercase_e = static_cast('e')); - BOOST_STATIC_CONSTANT(Char, capital_e = static_cast('E')); - BOOST_STATIC_CONSTANT(Char, c_decimal_separator = static_cast('.')); - }; - } -} // namespace boost - - -#endif // BOOST_LEXICAL_CAST_DETAIL_LCAST_CHAR_CONSTANTS_HPP - diff --git a/boost/lexical_cast/detail/lcast_unsigned_converters.hpp b/boost/lexical_cast/detail/lcast_unsigned_converters.hpp deleted file mode 100644 index e4a581e..0000000 --- a/boost/lexical_cast/detail/lcast_unsigned_converters.hpp +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP -#define BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifndef BOOST_NO_STD_LOCALE -# include -#else -# ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - // Getting error at this point means, that your STL library is old/lame/misconfigured. - // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE, - // but beware: lexical_cast will understand only 'C' locale delimeters and thousands - // separators. -# error "Unable to use header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force " -# error "boost::lexical_cast to use only 'C' locale during conversions." -# endif -#endif - -#include -#include -#include -#include - -namespace boost -{ - namespace detail // lcast_to_unsigned - { - template - inline - BOOST_DEDUCED_TYPENAME boost::make_unsigned::type lcast_to_unsigned(const T value) BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned::type result_type; - return value < 0 - ? static_cast(0u - static_cast(value)) - : static_cast(value); - } - } - - namespace detail // lcast_put_unsigned - { - template - class lcast_put_unsigned: boost::noncopyable { - typedef BOOST_DEDUCED_TYPENAME Traits::int_type int_type; - BOOST_DEDUCED_TYPENAME boost::conditional< - (sizeof(unsigned) > sizeof(T)) - , unsigned - , T - >::type m_value; - CharT* m_finish; - CharT const m_czero; - int_type const m_zero; - - public: - lcast_put_unsigned(const T n_param, CharT* finish) BOOST_NOEXCEPT - : m_value(n_param), m_finish(finish) - , m_czero(lcast_char_constants::zero), m_zero(Traits::to_int_type(m_czero)) - { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); -#endif - } - - CharT* convert() { -#ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - std::locale loc; - if (loc == std::locale::classic()) { - return main_convert_loop(); - } - - typedef std::numpunct numpunct; - numpunct const& np = BOOST_USE_FACET(numpunct, loc); - std::string const grouping = np.grouping(); - std::string::size_type const grouping_size = grouping.size(); - - if (!grouping_size || grouping[0] <= 0) { - return main_convert_loop(); - } - -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - // Check that ulimited group is unreachable: - BOOST_STATIC_ASSERT(std::numeric_limits::digits10 < CHAR_MAX); -#endif - CharT const thousands_sep = np.thousands_sep(); - std::string::size_type group = 0; // current group number - char last_grp_size = grouping[0]; - char left = last_grp_size; - - do { - if (left == 0) { - ++group; - if (group < grouping_size) { - char const grp_size = grouping[group]; - last_grp_size = (grp_size <= 0 ? static_cast(CHAR_MAX) : grp_size); - } - - left = last_grp_size; - --m_finish; - Traits::assign(*m_finish, thousands_sep); - } - - --left; - } while (main_convert_iteration()); - - return m_finish; -#else - return main_convert_loop(); -#endif - } - - private: - inline bool main_convert_iteration() BOOST_NOEXCEPT { - --m_finish; - int_type const digit = static_cast(m_value % 10U); - Traits::assign(*m_finish, Traits::to_char_type(m_zero + digit)); - m_value /= 10; - return !!m_value; // suppressing warnings - } - - inline CharT* main_convert_loop() BOOST_NOEXCEPT { - while (main_convert_iteration()); - return m_finish; - } - }; - } - - namespace detail // lcast_ret_unsigned - { - template - class lcast_ret_unsigned: boost::noncopyable { - bool m_multiplier_overflowed; - T m_multiplier; - T& m_value; - const CharT* const m_begin; - const CharT* m_end; - - public: - lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end) BOOST_NOEXCEPT - : m_multiplier_overflowed(false), m_multiplier(1), m_value(value), m_begin(begin), m_end(end) - { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); - - // GCC when used with flag -std=c++0x may not have std::numeric_limits - // specializations for __int128 and unsigned __int128 types. - // Try compilation with -std=gnu++0x or -std=gnu++11. - // - // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40856 - BOOST_STATIC_ASSERT_MSG(std::numeric_limits::is_specialized, - "std::numeric_limits are not specialized for integral type passed to boost::lexical_cast" - ); -#endif - } - - inline bool convert() { - CharT const czero = lcast_char_constants::zero; - --m_end; - m_value = static_cast(0); - - if (m_begin > m_end || *m_end < czero || *m_end >= czero + 10) - return false; - m_value = static_cast(*m_end - czero); - --m_end; - -#ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE - return main_convert_loop(); -#else - std::locale loc; - if (loc == std::locale::classic()) { - return main_convert_loop(); - } - - typedef std::numpunct numpunct; - numpunct const& np = BOOST_USE_FACET(numpunct, loc); - std::string const& grouping = np.grouping(); - std::string::size_type const grouping_size = grouping.size(); - - /* According to Programming languages - C++ - * we MUST check for correct grouping - */ - if (!grouping_size || grouping[0] <= 0) { - return main_convert_loop(); - } - - unsigned char current_grouping = 0; - CharT const thousands_sep = np.thousands_sep(); - char remained = static_cast(grouping[current_grouping] - 1); - - for (;m_end >= m_begin; --m_end) - { - if (remained) { - if (!main_convert_iteration()) { - return false; - } - --remained; - } else { - if ( !Traits::eq(*m_end, thousands_sep) ) //|| begin == end ) return false; - { - /* - * According to Programming languages - C++ - * Digit grouping is checked. That is, the positions of discarded - * separators is examined for consistency with - * use_facet >(loc ).grouping() - * - * BUT what if there is no separators at all and grouping() - * is not empty? Well, we have no extraced separators, so we - * won`t check them for consistency. This will allow us to - * work with "C" locale from other locales - */ - return main_convert_loop(); - } else { - if (m_begin == m_end) return false; - if (current_grouping < grouping_size - 1) ++current_grouping; - remained = grouping[current_grouping]; - } - } - } /*for*/ - - return true; -#endif - } - - private: - // Iteration that does not care about grouping/separators and assumes that all - // input characters are digits - inline bool main_convert_iteration() BOOST_NOEXCEPT { - CharT const czero = lcast_char_constants::zero; - T const maxv = (std::numeric_limits::max)(); - - m_multiplier_overflowed = m_multiplier_overflowed || (maxv/10 < m_multiplier); - m_multiplier = static_cast(m_multiplier * 10); - - T const dig_value = static_cast(*m_end - czero); - T const new_sub_value = static_cast(m_multiplier * dig_value); - - // We must correctly handle situations like `000000000000000000000000000001`. - // So we take care of overflow only if `dig_value` is not '0'. - if (*m_end < czero || *m_end >= czero + 10 // checking for correct digit - || (dig_value && ( // checking for overflow of ... - m_multiplier_overflowed // ... multiplier - || static_cast(maxv / dig_value) < m_multiplier // ... subvalue - || static_cast(maxv - new_sub_value) < m_value // ... whole expression - )) - ) return false; - - m_value = static_cast(m_value + new_sub_value); - - return true; - } - - bool main_convert_loop() BOOST_NOEXCEPT { - for ( ; m_end >= m_begin; --m_end) { - if (!main_convert_iteration()) { - return false; - } - } - - return true; - } - }; - } -} // namespace boost - -#endif // BOOST_LEXICAL_CAST_DETAIL_LCAST_UNSIGNED_CONVERTERS_HPP - diff --git a/boost/lexical_cast/detail/widest_char.hpp b/boost/lexical_cast/detail/widest_char.hpp deleted file mode 100644 index ca1e39d..0000000 --- a/boost/lexical_cast/detail/widest_char.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP -#define BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - - -#include - -namespace boost { namespace detail { - - template - struct widest_char { - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - (sizeof(TargetChar) > sizeof(SourceChar)) - , TargetChar - , SourceChar - >::type type; - }; - -}} // namespace boost::detail - -#endif // BOOST_LEXICAL_CAST_DETAIL_WIDEST_CHAR_HPP - diff --git a/boost/lexical_cast/try_lexical_convert.hpp b/boost/lexical_cast/try_lexical_convert.hpp deleted file mode 100644 index d326f12..0000000 --- a/boost/lexical_cast/try_lexical_convert.hpp +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright Kevlin Henney, 2000-2005. -// Copyright Alexander Nasonov, 2006-2010. -// Copyright Antony Polukhin, 2011-2023. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// what: lexical_cast custom keyword cast -// who: contributed by Kevlin Henney, -// enhanced with contributions from Terje Slettebo, -// with additional fixes and suggestions from Gennaro Prota, -// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, -// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann, -// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters -// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014 - -#ifndef BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP -#define BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#if defined(__clang__) || (defined(__GNUC__) && \ - !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -namespace boost { - namespace detail - { - template - struct is_stdstring - : boost::false_type - {}; - - template - struct is_stdstring< std::basic_string > - : boost::true_type - {}; - - // Sun Studio has problem with partial specialization of templates differing only in namespace. - // We workaround that by making `is_booststring` trait, instead of specializing `is_stdstring` for `boost::container::basic_string`. - template - struct is_booststring - : boost::false_type - {}; - - template - struct is_booststring< boost::container::basic_string > - : boost::true_type - {}; - - template - struct is_arithmetic_and_not_xchars - { - typedef boost::integral_constant< - bool, - !(boost::detail::is_character::value) && - !(boost::detail::is_character::value) && - boost::is_arithmetic::value && - boost::is_arithmetic::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = ( - type::value - )); - }; - - /* - * is_xchar_to_xchar::value is true, - * Target and Souce are char types of the same size 1 (char, signed char, unsigned char). - */ - template - struct is_xchar_to_xchar - { - typedef boost::integral_constant< - bool, - sizeof(Source) == sizeof(Target) && - sizeof(Source) == sizeof(char) && - boost::detail::is_character::value && - boost::detail::is_character::value - > type; - - BOOST_STATIC_CONSTANT(bool, value = ( - type::value - )); - }; - - template - struct is_char_array_to_stdstring - : boost::false_type - {}; - - template - struct is_char_array_to_stdstring< std::basic_string, CharT* > - : boost::true_type - {}; - - template - struct is_char_array_to_stdstring< std::basic_string, const CharT* > - : boost::true_type - {}; - - // Sun Studio has problem with partial specialization of templates differing only in namespace. - // We workaround that by making `is_char_array_to_booststring` trait, instead of specializing `is_char_array_to_stdstring` for `boost::container::basic_string`. - template - struct is_char_array_to_booststring - : boost::false_type - {}; - - template - struct is_char_array_to_booststring< boost::container::basic_string, CharT* > - : boost::true_type - {}; - - template - struct is_char_array_to_booststring< boost::container::basic_string, const CharT* > - : boost::true_type - {}; - - template - struct copy_converter_impl - { -// MSVC fail to forward an array (DevDiv#555157 "SILENT BAD CODEGEN triggered by perfect forwarding", -// fixed in 2013 RTM). -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(BOOST_MSVC) || BOOST_MSVC >= 1800) - template - static inline bool try_convert(T&& arg, Target& result) { - result = static_cast(arg); // eqaul to `result = std::forward(arg);` - return true; - } -#else - static inline bool try_convert(const Source& arg, Target& result) { - result = arg; - return true; - } -#endif - }; - } - - namespace conversion { namespace detail { - - template - inline bool try_lexical_convert(const Source& arg, Target& result) - { - typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay::type src; - - typedef boost::integral_constant< - bool, - boost::detail::is_xchar_to_xchar::value || - boost::detail::is_char_array_to_stdstring::value || - boost::detail::is_char_array_to_booststring::value || - ( - boost::is_same::value && - (boost::detail::is_stdstring::value || boost::detail::is_booststring::value) - ) || - ( - boost::is_same::value && - boost::detail::is_character::value - ) - > shall_we_copy_t; - - typedef boost::detail::is_arithmetic_and_not_xchars - shall_we_copy_with_dynamic_check_t; - - // We do evaluate second `if_` lazily to avoid unnecessary instantiations - // of `shall_we_copy_with_dynamic_check_t` and improve compilation times. - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - shall_we_copy_t::value, - boost::type_identity >, - boost::conditional< - shall_we_copy_with_dynamic_check_t::value, - boost::detail::dynamic_num_converter_impl, - boost::detail::lexical_converter_impl - > - >::type caster_type_lazy; - - typedef BOOST_DEDUCED_TYPENAME caster_type_lazy::type caster_type; - - return caster_type::try_convert(arg, result); - } - - template - inline bool try_lexical_convert(const CharacterT* chars, std::size_t count, Target& result) - { - BOOST_STATIC_ASSERT_MSG( - boost::detail::is_character::value, - "This overload of try_lexical_convert is meant to be used only with arrays of characters." - ); - return ::boost::conversion::detail::try_lexical_convert( - ::boost::iterator_range(chars, chars + count), result - ); - } - - }} // namespace conversion::detail - - namespace conversion { - // ADL barrier - using ::boost::conversion::detail::try_lexical_convert; - } - -} // namespace boost - -#if defined(__clang__) || (defined(__GNUC__) && \ - !(defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))) -#pragma GCC diagnostic pop -#endif - -#endif // BOOST_LEXICAL_CAST_TRY_LEXICAL_CONVERT_HPP - diff --git a/boost/locale/config.hpp b/boost/locale/config.hpp index 821ba7f..9c8e6c2 100644 --- a/boost/locale/config.hpp +++ b/boost/locale/config.hpp @@ -72,6 +72,16 @@ #else # define BOOST_LOCALE_USE_WIN32_API 0 #endif + +// To be used to suppress false positives of UBSAN +#if defined(__clang__) && defined(__has_attribute) +# if __has_attribute(no_sanitize) +# define BOOST_LOCALE_NO_SANITIZE(what) __attribute__((no_sanitize(what))) +# endif +#endif +#if !defined(BOOST_LOCALE_NO_SANITIZE) +# define BOOST_LOCALE_NO_SANITIZE(what) +#endif /// \endcond #endif // boost/locale/config.hpp diff --git a/boost/locale/encoding_errors.hpp b/boost/locale/encoding_errors.hpp index 6643a63..97f0f6b 100644 --- a/boost/locale/encoding_errors.hpp +++ b/boost/locale/encoding_errors.hpp @@ -33,7 +33,7 @@ namespace boost { namespace locale { namespace conv { public: /// Create an error for charset \a charset invalid_charset_error(const std::string& charset) : - std::runtime_error("Invalid or unsupported charset:" + charset) + std::runtime_error("Invalid or unsupported charset: " + charset) {} }; diff --git a/boost/locale/encoding_utf.hpp b/boost/locale/encoding_utf.hpp index ed1e5db..c19e67d 100644 --- a/boost/locale/encoding_utf.hpp +++ b/boost/locale/encoding_utf.hpp @@ -23,27 +23,28 @@ namespace boost { namespace locale { namespace conv { /// @{ /// Convert a Unicode text in range [begin,end) to other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template std::basic_string utf_to_utf(const CharIn* begin, const CharIn* end, method_type how = default_method) { std::basic_string result; result.reserve(end - begin); - typedef std::back_insert_iterator> inserter_type; - inserter_type inserter(result); - utf::code_point c; + std::back_insert_iterator> inserter(result); while(begin != end) { - c = utf::utf_traits::template decode(begin, end); + const utf::code_point c = utf::utf_traits::decode(begin, end); if(c == utf::illegal || c == utf::incomplete) { if(how == stop) throw conversion_error(); - } else { - utf::utf_traits::template encode(c, inserter); - } + } else + utf::utf_traits::encode(c, inserter); } return result; } /// Convert a Unicode NULL terminated string \a str other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template std::basic_string utf_to_utf(const CharIn* str, method_type how = default_method) { @@ -51,6 +52,8 @@ namespace boost { namespace locale { namespace conv { } /// Convert a Unicode string \a str other Unicode encoding + /// + /// \throws conversion_error: Conversion failed (e.g. \a how is \c stop and any character cannot be decoded) template std::basic_string utf_to_utf(const std::basic_string& str, method_type how = default_method) { diff --git a/boost/locale/utf.hpp b/boost/locale/utf.hpp index 841b10f..a30f736 100644 --- a/boost/locale/utf.hpp +++ b/boost/locale/utf.hpp @@ -8,7 +8,7 @@ #define BOOST_LOCALE_UTF_HPP_INCLUDED #include -#include +#include namespace boost { namespace locale { /// \brief Namespace that holds basic operations on UTF encoded sequences @@ -16,13 +16,16 @@ namespace boost { namespace locale { /// All functions defined in this namespace do not require linking with Boost.Locale library namespace utf { /// \brief The integral type that can hold a Unicode code point - typedef uint32_t code_point; + using code_point = uint32_t; /// \brief Special constant that defines illegal code point constexpr code_point illegal = 0xFFFFFFFFu; /// \brief Special constant that defines incomplete code point constexpr code_point incomplete = 0xFFFFFFFEu; + /// Either a length/size or an error (illegal/incomplete) + using len_or_error = code_point; + /// \brief the function checks if \a v is a valid code point inline bool is_valid_codepoint(code_point v) { @@ -125,15 +128,14 @@ namespace boost { namespace locale { static int width(code_point value) { - if(value <= 0x7F) { + if(value <= 0x7F) return 1; - } else if(value <= 0x7FF) { + else if(value <= 0x7FF) return 2; - } else if(BOOST_LIKELY(value <= 0xFFFF)) { + else if(BOOST_LIKELY(value <= 0xFFFF)) return 3; - } else { + else return 4; - } } static bool is_trail(char_type ci) @@ -235,9 +237,9 @@ namespace boost { namespace locale { template static Iterator encode(code_point value, Iterator out) { - if(value <= 0x7F) { + if(value <= 0x7F) *out++ = static_cast(value); - } else if(value <= 0x7FF) { + else if(value <= 0x7FF) { *out++ = static_cast((value >> 6) | 0xC0); *out++ = static_cast((value & 0x3F) | 0x80); } else if(BOOST_LIKELY(value <= 0xFFFF)) { @@ -285,9 +287,8 @@ namespace boost { namespace locale { if(BOOST_UNLIKELY(current == last)) return incomplete; uint16_t w1 = *current++; - if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) return w1; - } if(w1 > 0xDBFF) return illegal; if(current == last) @@ -301,9 +302,8 @@ namespace boost { namespace locale { static code_point decode_valid(It& current) { uint16_t w1 = *current++; - if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) { + if(BOOST_LIKELY(w1 < 0xD800 || 0xDFFF < w1)) return w1; - } uint16_t w2 = *current++; return combine_surrogate(w1, w2); } @@ -313,9 +313,9 @@ namespace boost { namespace locale { template static It encode(code_point u, It out) { - if(BOOST_LIKELY(u <= 0xFFFF)) { + if(BOOST_LIKELY(u <= 0xFFFF)) *out++ = static_cast(u); - } else { + else { u -= 0x10000; *out++ = static_cast(0xD800 | (u >> 10)); *out++ = static_cast(0xDC00 | (u & 0x3FF)); diff --git a/boost/locale/util/string.hpp b/boost/locale/util/string.hpp index 14e52e6..9ab9521 100644 --- a/boost/locale/util/string.hpp +++ b/boost/locale/util/string.hpp @@ -8,6 +8,7 @@ #define BOOST_LOCALE_UTIL_STRING_HPP #include +#include namespace boost { namespace locale { namespace util { /// Return the end of a C-string, i.e. the pointer to the trailing NULL byte @@ -19,21 +20,27 @@ namespace boost { namespace locale { namespace util { return str; } - inline bool is_upper_ascii(const char c) + inline constexpr bool is_upper_ascii(const char c) { return 'A' <= c && c <= 'Z'; } - inline bool is_lower_ascii(const char c) + inline constexpr bool is_lower_ascii(const char c) { return 'a' <= c && c <= 'z'; } - inline bool is_numeric_ascii(const char c) + inline constexpr bool is_numeric_ascii(const char c) { return '0' <= c && c <= '9'; } + /// Cast an unsigned char to a (possibly signed) char avoiding implementation defined behavior + constexpr char to_char(unsigned char c) + { + return static_cast((c - std::numeric_limits::min()) + std::numeric_limits::min()); + } + }}} // namespace boost::locale::util #endif \ No newline at end of file diff --git a/boost/memory_order.hpp b/boost/memory_order.hpp new file mode 100644 index 0000000..ba7d1cd --- /dev/null +++ b/boost/memory_order.hpp @@ -0,0 +1,82 @@ +// boost/memory_order.hpp +// +// Defines enum boost::memory_order per the C++0x working draft +// +// Copyright (c) 2008, 2009 Peter Dimov +// Copyright (c) 2018 Andrey Semashev +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED +#define BOOST_MEMORY_ORDER_HPP_INCLUDED + +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost +{ + +// +// Enum values are chosen so that code that needs to insert +// a trailing fence for acquire semantics can use a single +// test such as: +// +// if( mo & memory_order_acquire ) { ...fence... } +// +// For leading fences one can use: +// +// if( mo & memory_order_release ) { ...fence... } +// +// Architectures such as Alpha that need a fence on consume +// can use: +// +// if( mo & ( memory_order_acquire | memory_order_consume ) ) { ...fence... } +// +// The values are also in the order of increasing "strength" +// of the fences so that success/failure orders can be checked +// efficiently in compare_exchange methods. +// + +#if !defined(BOOST_NO_CXX11_SCOPED_ENUMS) + +enum class memory_order : unsigned int +{ + relaxed = 0, + consume = 1, + acquire = 2, + release = 4, + acq_rel = 6, // acquire | release + seq_cst = 14 // acq_rel | 8 +}; + +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_relaxed = memory_order::relaxed; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_consume = memory_order::consume; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_acquire = memory_order::acquire; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_release = memory_order::release; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_acq_rel = memory_order::acq_rel; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST memory_order memory_order_seq_cst = memory_order::seq_cst; + +#undef BOOST_MEMORY_ORDER_INLINE_VARIABLE + +#else // !defined(BOOST_NO_CXX11_SCOPED_ENUMS) + +enum memory_order +{ + memory_order_relaxed = 0, + memory_order_consume = 1, + memory_order_acquire = 2, + memory_order_release = 4, + memory_order_acq_rel = 6, // acquire | release + memory_order_seq_cst = 14 // acq_rel | 8 +}; + +#endif // !defined(BOOST_NO_CXX11_SCOPED_ENUMS) + +} // namespace boost + +#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED diff --git a/boost/mp11/algorithm.hpp b/boost/mp11/algorithm.hpp index 60987a8..be377f5 100644 --- a/boost/mp11/algorithm.hpp +++ b/boost/mp11/algorithm.hpp @@ -199,7 +199,10 @@ template using mp_filter_q = typename detail::mp_filter_imp namespace detail { -template struct mp_fill_impl; +template struct mp_fill_impl +{ +// An error "no type named 'type'" here means that the L argument of mp_fill is not a list +}; template class L, class... T, class V> struct mp_fill_impl, V> { @@ -216,6 +219,15 @@ template class L, class... T, class V> struct mp_fill_impl class L, auto... A, class V> struct mp_fill_impl, V> +{ + using type = L<((void)A, V::value)...>; +}; + +#endif + } // namespace detail template using mp_fill = typename detail::mp_fill_impl::type; @@ -297,35 +309,35 @@ template class L, class... T, template class L2, cl { template static mp_identity> f( U*..., mp_identity*... ); - using R = decltype( f( (mp_identity*)0 ... ) ); + using R = decltype( f( static_cast*>(0) ... ) ); using type = typename R::type; }; } // namespace detail -template using mp_drop_c = typename detail::mp_drop_impl, N>, mp_bool::value>>::type; +template using mp_drop_c = mp_assign, mp_repeat_c, N>, mp_bool::value>>::type>; template using mp_drop = mp_drop_c; -// mp_from_sequence +// mp_from_sequence namespace detail { -template struct mp_from_sequence_impl; +template struct mp_from_sequence_impl; -template class S, class U, U... J> struct mp_from_sequence_impl> +template class S, class U, U... J, class F> struct mp_from_sequence_impl, F> { - using type = mp_list...>; + using type = mp_list_c; }; } // namespace detail -template using mp_from_sequence = typename detail::mp_from_sequence_impl::type; +template> using mp_from_sequence = typename detail::mp_from_sequence_impl::type; -// mp_iota(_c) -template using mp_iota_c = mp_from_sequence>; -template using mp_iota = mp_from_sequence::type, N::value>>; +// mp_iota(_c) +template using mp_iota_c = mp_from_sequence, mp_size_t>; +template> using mp_iota = mp_from_sequence::type, N::value>, F>; // mp_at(_c) namespace detail @@ -340,11 +352,20 @@ template class L, class... T, std::size_t I> struct mp_at_c_i using type = __type_pack_element; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, std::size_t I> struct mp_at_c_impl, I> +{ + using type = __type_pack_element...>; +}; + +#endif + #else template struct mp_at_c_impl { - using _map = mp_transform >, L>; + using _map = mp_transform >, mp_rename>; using type = mp_second > >; }; @@ -449,8 +470,8 @@ struct mp_take_c_impl, typen } // namespace detail -template using mp_take_c = typename detail::mp_take_c_impl::type; -template using mp_take = typename detail::mp_take_c_impl::type; +template using mp_take_c = mp_assign>::type>; +template using mp_take = mp_take_c; // mp_back template using mp_back = mp_at_c::value - 1>; diff --git a/boost/mp11/detail/config.hpp b/boost/mp11/detail/config.hpp index 764bd59..44686c7 100644 --- a/boost/mp11/detail/config.hpp +++ b/boost/mp11/detail/config.hpp @@ -123,6 +123,17 @@ # endif #endif +// BOOST_MP11_HAS_TEMPLATE_AUTO + +#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L +# define BOOST_MP11_HAS_TEMPLATE_AUTO +#endif + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) +// mp_value<0> is bool, mp_value<-1L> is int, etc +# undef BOOST_MP11_HAS_TEMPLATE_AUTO +#endif + // BOOST_MP11_DEPRECATED(msg) #if BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, < 304 ) diff --git a/boost/mp11/detail/mp_append.hpp b/boost/mp11/detail/mp_append.hpp index 937d15e..858ee24 100644 --- a/boost/mp11/detail/mp_append.hpp +++ b/boost/mp11/detail/mp_append.hpp @@ -8,7 +8,10 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#include +#include #include +#include #include #include @@ -22,6 +25,8 @@ namespace mp11 namespace detail { +// append_type_lists + template struct mp_append_impl; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) @@ -167,17 +172,148 @@ template struct mp_append_impl: mp_append_impl_cuda_workaround #else -template struct mp_append_impl: mp_if_c<(sizeof...(L) > 111), mp_quote, mp_if_c<(sizeof...(L) > 11), mp_quote, mp_quote > >::template fn +template struct mp_append_impl: + mp_cond< + mp_bool<(sizeof...(L) > 111)>, mp_quote, + mp_bool<(sizeof...(L) > 11)>, mp_quote, + mp_true, mp_quote + >::template fn { }; -#endif +#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) -#endif +#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +struct append_type_lists +{ + template using fn = typename mp_append_impl::type; +}; + +// append_value_lists + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template struct append_value_impl; + +template, class L2 = mp_list_v<>, class L3 = mp_list_v<>, class L4 = mp_list_v<>, class L5 = mp_list_v<>, class L6 = mp_list_v<>, class L7 = mp_list_v<>, class L8 = mp_list_v<>, class L9 = mp_list_v<>, class L10 = mp_list_v<>, class L11 = mp_list_v<>> struct append_value_11_impl +{ +}; + +template< + template class L1, auto... T1, + template class L2, auto... T2, + template class L3, auto... T3, + template class L4, auto... T4, + template class L5, auto... T5, + template class L6, auto... T6, + template class L7, auto... T7, + template class L8, auto... T8, + template class L9, auto... T9, + template class L10, auto... T10, + template class L11, auto... T11> + +struct append_value_11_impl, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11> +{ + using type = L1; +}; + +template< + + class L00 = mp_list_v<>, class L01 = mp_list_v<>, class L02 = mp_list_v<>, class L03 = mp_list_v<>, class L04 = mp_list_v<>, class L05 = mp_list_v<>, class L06 = mp_list_v<>, class L07 = mp_list_v<>, class L08 = mp_list_v<>, class L09 = mp_list_v<>, class L0A = mp_list_v<>, + class L10 = mp_list_v<>, class L11 = mp_list_v<>, class L12 = mp_list_v<>, class L13 = mp_list_v<>, class L14 = mp_list_v<>, class L15 = mp_list_v<>, class L16 = mp_list_v<>, class L17 = mp_list_v<>, class L18 = mp_list_v<>, class L19 = mp_list_v<>, + class L20 = mp_list_v<>, class L21 = mp_list_v<>, class L22 = mp_list_v<>, class L23 = mp_list_v<>, class L24 = mp_list_v<>, class L25 = mp_list_v<>, class L26 = mp_list_v<>, class L27 = mp_list_v<>, class L28 = mp_list_v<>, class L29 = mp_list_v<>, + class L30 = mp_list_v<>, class L31 = mp_list_v<>, class L32 = mp_list_v<>, class L33 = mp_list_v<>, class L34 = mp_list_v<>, class L35 = mp_list_v<>, class L36 = mp_list_v<>, class L37 = mp_list_v<>, class L38 = mp_list_v<>, class L39 = mp_list_v<>, + class L40 = mp_list_v<>, class L41 = mp_list_v<>, class L42 = mp_list_v<>, class L43 = mp_list_v<>, class L44 = mp_list_v<>, class L45 = mp_list_v<>, class L46 = mp_list_v<>, class L47 = mp_list_v<>, class L48 = mp_list_v<>, class L49 = mp_list_v<>, + class L50 = mp_list_v<>, class L51 = mp_list_v<>, class L52 = mp_list_v<>, class L53 = mp_list_v<>, class L54 = mp_list_v<>, class L55 = mp_list_v<>, class L56 = mp_list_v<>, class L57 = mp_list_v<>, class L58 = mp_list_v<>, class L59 = mp_list_v<>, + class L60 = mp_list_v<>, class L61 = mp_list_v<>, class L62 = mp_list_v<>, class L63 = mp_list_v<>, class L64 = mp_list_v<>, class L65 = mp_list_v<>, class L66 = mp_list_v<>, class L67 = mp_list_v<>, class L68 = mp_list_v<>, class L69 = mp_list_v<>, + class L70 = mp_list_v<>, class L71 = mp_list_v<>, class L72 = mp_list_v<>, class L73 = mp_list_v<>, class L74 = mp_list_v<>, class L75 = mp_list_v<>, class L76 = mp_list_v<>, class L77 = mp_list_v<>, class L78 = mp_list_v<>, class L79 = mp_list_v<>, + class L80 = mp_list_v<>, class L81 = mp_list_v<>, class L82 = mp_list_v<>, class L83 = mp_list_v<>, class L84 = mp_list_v<>, class L85 = mp_list_v<>, class L86 = mp_list_v<>, class L87 = mp_list_v<>, class L88 = mp_list_v<>, class L89 = mp_list_v<>, + class L90 = mp_list_v<>, class L91 = mp_list_v<>, class L92 = mp_list_v<>, class L93 = mp_list_v<>, class L94 = mp_list_v<>, class L95 = mp_list_v<>, class L96 = mp_list_v<>, class L97 = mp_list_v<>, class L98 = mp_list_v<>, class L99 = mp_list_v<>, + class LA0 = mp_list_v<>, class LA1 = mp_list_v<>, class LA2 = mp_list_v<>, class LA3 = mp_list_v<>, class LA4 = mp_list_v<>, class LA5 = mp_list_v<>, class LA6 = mp_list_v<>, class LA7 = mp_list_v<>, class LA8 = mp_list_v<>, class LA9 = mp_list_v<> + +> struct append_value_111_impl +{ + using type = typename append_value_11_impl< + + typename append_value_11_impl::type, + typename append_value_11_impl, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type, + typename append_value_11_impl, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type, + typename append_value_11_impl, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type, + typename append_value_11_impl, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type, + typename append_value_11_impl, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type, + typename append_value_11_impl, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type, + typename append_value_11_impl, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type, + typename append_value_11_impl, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type, + typename append_value_11_impl, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type, + typename append_value_11_impl, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type + + >::type; +}; + +template< + + class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A, + class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19, + class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29, + class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39, + class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49, + class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59, + class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69, + class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79, + class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89, + class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99, + class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9, + class... Lr + +> struct append_value_inf_impl +{ + using prefix = typename append_value_111_impl< + + L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A, + L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, + L20, L21, L22, L23, L24, L25, L26, L27, L28, L29, + L30, L31, L32, L33, L34, L35, L36, L37, L38, L39, + L40, L41, L42, L43, L44, L45, L46, L47, L48, L49, + L50, L51, L52, L53, L54, L55, L56, L57, L58, L59, + L60, L61, L62, L63, L64, L65, L66, L67, L68, L69, + L70, L71, L72, L73, L74, L75, L76, L77, L78, L79, + L80, L81, L82, L83, L84, L85, L86, L87, L88, L89, + L90, L91, L92, L93, L94, L95, L96, L97, L98, L99, + LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9 + + >::type; + + using type = typename append_value_impl::type; +}; + +template struct append_value_impl: + mp_cond< + mp_bool<(sizeof...(L) > 111)>, mp_quote, + mp_bool<(sizeof...(L) > 11)>, mp_quote, + mp_true, mp_quote + >::template fn +{ +}; + +struct append_value_lists +{ + template using fn = typename append_value_impl::type; +}; + +#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) } // namespace detail -template using mp_append = typename detail::mp_append_impl::type; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template using mp_append = typename mp_if_c<(sizeof...(L) > 0 && sizeof...(L) == mp_count_if, mp_is_value_list>::value), detail::append_value_lists, detail::append_type_lists>::template fn; + +#else + +template using mp_append = detail::append_type_lists::fn; + +#endif } // namespace mp11 } // namespace boost diff --git a/boost/mp11/detail/mp_defer.hpp b/boost/mp11/detail/mp_defer.hpp new file mode 100644 index 0000000..9aaca99 --- /dev/null +++ b/boost/mp11/detail/mp_defer.hpp @@ -0,0 +1,119 @@ +#ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED + +// Copyright 2015-2020, 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_if, mp_if_c +namespace detail +{ + +template struct mp_if_c_impl +{ +}; + +template struct mp_if_c_impl +{ + using type = T; +}; + +template struct mp_if_c_impl +{ + using type = E; +}; + +} // namespace detail + +template using mp_if_c = typename detail::mp_if_c_impl::type; +template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; + +// mp_valid + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 + +// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 + +namespace detail +{ + +template using void_t = void; + +template class F, class... T> +struct mp_valid_impl: mp_false {}; + +template class F, class... T> +struct mp_valid_impl>, F, T...>: mp_true {}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl; + +#else + +// implementation by Bruno Dutra (by the name is_evaluable) +namespace detail +{ + +template class F, class... T> struct mp_valid_impl +{ + template class G, class = G> static mp_true check(int); + template class> static mp_false check(...); + + using type = decltype(check(0)); +}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; + +#endif + +template using mp_valid_q = mp_valid; + +// mp_defer +namespace detail +{ + +template class F, class... T> struct mp_defer_impl +{ + using type = F; +}; + +struct mp_no_type +{ +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> struct mp_defer_cuda_workaround +{ + using type = mp_if, detail::mp_defer_impl, detail::mp_no_type>; +}; + +#endif + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; + +#else + +template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_fold.hpp b/boost/mp11/detail/mp_fold.hpp index 0745e87..266d9c1 100644 --- a/boost/mp11/detail/mp_fold.hpp +++ b/boost/mp11/detail/mp_fold.hpp @@ -9,6 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt #include +#include namespace boost { @@ -41,12 +42,113 @@ template class L, class V, template class F> struct #endif -template class L, class T1, class... T, class V, template class F> struct mp_fold_impl, V, F> +// + +template class F> struct mp_fold_Q1 { - using type = typename mp_fold_impl, F, F>::type; + template + using fn = F; }; -template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> struct mp_fold_impl, V, F> +template class F> struct mp_fold_Q2 +{ + template + using fn = F, T2>; +}; + +template class F> struct mp_fold_Q3 +{ + template + using fn = F, T2>, T3>; +}; + +template class F> struct mp_fold_Q4 +{ + template + using fn = F, T2>, T3>, T4>; +}; + +template class F> struct mp_fold_Q5 +{ + template + using fn = F, T2>, T3>, T4>, T5>; +}; + +template class F> struct mp_fold_Q6 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>; +}; + +template class F> struct mp_fold_Q7 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>; +}; + +template class F> struct mp_fold_Q8 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>; +}; + +template class F> struct mp_fold_Q9 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>; +}; + +// + +template class L, class T1, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1> +{ +}; + +template class L, class T1, class T2, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2> +{ +}; + +template class L, class T1, class T2, class T3, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9> +{ +}; + +// + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> +struct mp_fold_impl, V, F> { using type = typename mp_fold_impl, F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type; }; diff --git a/boost/mp11/detail/mp_front.hpp b/boost/mp11/detail/mp_front.hpp index de83d09..53a73ac 100644 --- a/boost/mp11/detail/mp_front.hpp +++ b/boost/mp11/detail/mp_front.hpp @@ -1,13 +1,16 @@ #ifndef BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED #define BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED -// Copyright 2015-2021 Peter Dimov. +// Copyright 2015-2023 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#include +#include + namespace boost { namespace mp11 @@ -28,6 +31,15 @@ template class L, class T1, class... T> struct mp_front_impl< using type = T1; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A> struct mp_front_impl> +{ + using type = mp_value; +}; + +#endif + } // namespace detail template using mp_front = typename detail::mp_front_impl::type; diff --git a/boost/mp11/detail/mp_is_value_list.hpp b/boost/mp11/detail/mp_is_value_list.hpp new file mode 100644 index 0000000..8f94f03 --- /dev/null +++ b/boost/mp11/detail/mp_is_value_list.hpp @@ -0,0 +1,41 @@ +#ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_is_value_list +namespace detail +{ + +template struct mp_is_value_list_impl +{ + using type = mp_false; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A> struct mp_is_value_list_impl> +{ + using type = mp_true; +}; + +#endif + +} // namespace detail + +template using mp_is_value_list = typename detail::mp_is_value_list_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_list_v.hpp b/boost/mp11/detail/mp_list_v.hpp new file mode 100644 index 0000000..bc05238 --- /dev/null +++ b/boost/mp11/detail/mp_list_v.hpp @@ -0,0 +1,27 @@ +#ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// http://www.boost.org/LICENSE_1_0.txt + +#include + +namespace boost +{ +namespace mp11 +{ + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +// mp_list_v +template struct mp_list_v +{ +}; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_map_find.hpp b/boost/mp11/detail/mp_map_find.hpp index 5ba58a4..2fb70d8 100644 --- a/boost/mp11/detail/mp_map_find.hpp +++ b/boost/mp11/detail/mp_map_find.hpp @@ -74,7 +74,7 @@ template class M, class... T, class K> struct mp_map_find_imp template class L, class... U> static mp_identity> f( mp_identity>* ); static mp_identity f( ... ); - using type = mpmf_unwrap< decltype( f((U*)0) ) >; + using type = mpmf_unwrap< decltype( f( static_cast(0) ) ) >; }; } // namespace detail diff --git a/boost/mp11/detail/mp_plus.hpp b/boost/mp11/detail/mp_plus.hpp index 90ed4c9..5c9417c 100644 --- a/boost/mp11/detail/mp_plus.hpp +++ b/boost/mp11/detail/mp_plus.hpp @@ -20,7 +20,10 @@ namespace mp11 namespace detail { -#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) +#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, != 0 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, != 0 ) + +// msvc fails with parser stack overflow for large sizeof...(T) +// clang exceeds -fbracket-depth, which defaults to 256 template struct mp_plus_impl { diff --git a/boost/mp11/detail/mp_rename.hpp b/boost/mp11/detail/mp_rename.hpp index 8368ac6..dde8f6f 100644 --- a/boost/mp11/detail/mp_rename.hpp +++ b/boost/mp11/detail/mp_rename.hpp @@ -1,13 +1,17 @@ #ifndef BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED #define BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED -// Copyright 2015-2021 Peter Dimov. +// Copyright 2015-2023 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#include +#include +#include + namespace boost { namespace mp11 @@ -17,22 +21,31 @@ namespace mp11 namespace detail { -template class B> struct mp_rename_impl +template class B> struct mp_rename_impl { // An error "no type named 'type'" here means that the first argument to mp_rename is not a list }; -template class A, class... T, template class B> struct mp_rename_impl, B> +template class L, class... T, template class B> struct mp_rename_impl, B>: mp_defer { - using type = B; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, template class B> struct mp_rename_impl, B>: mp_defer...> +{ +}; + +#endif + } // namespace detail -template class B> using mp_rename = typename detail::mp_rename_impl::type; +template class B> using mp_rename = typename detail::mp_rename_impl::type; +// mp_apply template class F, class L> using mp_apply = typename detail::mp_rename_impl::type; +// mp_apply_q template using mp_apply_q = typename detail::mp_rename_impl::type; } // namespace mp11 diff --git a/boost/mp11/detail/mp_value.hpp b/boost/mp11/detail/mp_value.hpp new file mode 100644 index 0000000..d0e5982 --- /dev/null +++ b/boost/mp11/detail/mp_value.hpp @@ -0,0 +1,25 @@ +#ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +namespace boost +{ +namespace mp11 +{ + +template using mp_value = std::integral_constant; + +} // namespace mp11 +} // namespace boost + +#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +#endif // #ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED diff --git a/boost/mp11/integral.hpp b/boost/mp11/integral.hpp index 0671673..1b4fea3 100644 --- a/boost/mp11/integral.hpp +++ b/boost/mp11/integral.hpp @@ -9,6 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt #include +#include #include #include diff --git a/boost/mp11/list.hpp b/boost/mp11/list.hpp index 6572a62..3646764 100644 --- a/boost/mp11/list.hpp +++ b/boost/mp11/list.hpp @@ -1,7 +1,7 @@ #ifndef BOOST_MP11_LIST_HPP_INCLUDED #define BOOST_MP11_LIST_HPP_INCLUDED -// Copyright 2015-2017 Peter Dimov. +// Copyright 2015-2023 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -10,10 +10,12 @@ #include #include +#include #include -#include +#include #include #include +#include #include #include @@ -22,12 +24,21 @@ namespace boost namespace mp11 { +// mp_list +// in detail/mp_list.hpp + // mp_list_c template using mp_list_c = mp_list...>; +// mp_list_v +// in detail/mp_list_v.hpp + // mp_is_list // in detail/mp_is_list.hpp +// mp_is_value_list +// in detail/mp_is_value_list.hpp + // mp_size namespace detail { @@ -42,6 +53,15 @@ template class L, class... T> struct mp_size_impl> using type = mp_size_t; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A> struct mp_size_impl> +{ + using type = mp_size_t; +}; + +#endif + } // namespace detail template using mp_size = typename detail::mp_size_impl::type; @@ -53,13 +73,35 @@ template using mp_empty = mp_bool< mp_size::value == 0 >; namespace detail { -template struct mp_assign_impl; +template struct mp_assign_impl +{ +// An error "no type named 'type'" here means that the arguments to mp_assign aren't lists +}; template class L1, class... T, template class L2, class... U> struct mp_assign_impl, L2> { using type = L1; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L1, auto... A, template class L2, class... U> struct mp_assign_impl, L2> +{ + using type = L1; +}; + +template class L1, class... T, template class L2, auto... B> struct mp_assign_impl, L2> +{ + using type = L1...>; +}; + +template class L1, auto... A, template class L2, auto... B> struct mp_assign_impl, L2> +{ + using type = L1; +}; + +#endif + } // namespace detail template using mp_assign = typename detail::mp_assign_impl::type; @@ -85,6 +127,15 @@ template class L, class T1, class... T> struct mp_pop_front_i using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A> struct mp_pop_front_impl> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_pop_front = typename detail::mp_pop_front_impl::type; @@ -110,6 +161,15 @@ template class L, class T1, class T2, class... T> struct mp_s using type = T2; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A> struct mp_second_impl> +{ + using type = mp_value; +}; + +#endif + } // namespace detail template using mp_second = typename detail::mp_second_impl::type; @@ -129,6 +189,15 @@ template class L, class T1, class T2, class T3, class... T> s using type = T3; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A> struct mp_third_impl> +{ + using type = mp_value; +}; + +#endif + } // namespace detail template using mp_third = typename detail::mp_third_impl::type; @@ -147,6 +216,15 @@ template class L, class... U, class... T> struct mp_push_fron using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, class... T> struct mp_push_front_impl, T...> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_push_front = typename detail::mp_push_front_impl::type; @@ -165,6 +243,15 @@ template class L, class... U, class... T> struct mp_push_back using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, class... T> struct mp_push_back_impl, T...> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_push_back = typename detail::mp_push_back_impl::type; @@ -174,6 +261,33 @@ template using mp_push_back = typename detail::mp_push_back // mp_apply_q // in detail/mp_rename.hpp +// mp_rename_v +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +namespace detail +{ + +template class B> struct mp_rename_v_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_rename_v is not a list +}; + +template class L, class... T, template class B> struct mp_rename_v_impl, B> +{ + using type = B; +}; + +template class L, auto... A, template class B> struct mp_rename_v_impl, B> +{ + using type = B; +}; + +} // namespace detail + +template class B> using mp_rename_v = typename detail::mp_rename_v_impl::type; + +#endif + // mp_replace_front namespace detail { @@ -189,6 +303,15 @@ template class L, class U1, class... U, class T> struct mp_re using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A, class T> struct mp_replace_front_impl, T> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_replace_front = typename detail::mp_replace_front_impl::type; @@ -211,6 +334,15 @@ template class L, class U1, class U2, class... U, class T> st using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A, class T> struct mp_replace_second_impl, T> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_replace_second = typename detail::mp_replace_second_impl::type; @@ -230,6 +362,15 @@ template class L, class U1, class U2, class U3, class... U, c using type = L; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A, class T> struct mp_replace_third_impl, T> +{ + using type = L; +}; + +#endif + } // namespace detail template using mp_replace_third = typename detail::mp_replace_third_impl::type; @@ -249,6 +390,15 @@ template class L, class U1, class... U, template cl using type = L, U...>; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A, template class F> struct mp_transform_front_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + } // namespace detail template class F> using mp_transform_front = typename detail::mp_transform_front_impl::type; @@ -273,6 +423,15 @@ template class L, class U1, class U2, class... U, template, U...>; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A, template class F> struct mp_transform_second_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + } // namespace detail template class F> using mp_transform_second = typename detail::mp_transform_second_impl::type; @@ -293,6 +452,15 @@ template class L, class U1, class U2, class U3, class... U, t using type = L, U...>; }; +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A, template class F> struct mp_transform_third_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + } // namespace detail template class F> using mp_transform_third = typename detail::mp_transform_third_impl::type; diff --git a/boost/mp11/utility.hpp b/boost/mp11/utility.hpp index fbab4a3..4010aee 100644 --- a/boost/mp11/utility.hpp +++ b/boost/mp11/utility.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace boost @@ -33,104 +34,9 @@ template using mp_identity_t = typename mp_identity::type; template struct mp_inherit: T... {}; // mp_if, mp_if_c -namespace detail -{ - -template struct mp_if_c_impl -{ -}; - -template struct mp_if_c_impl -{ - using type = T; -}; - -template struct mp_if_c_impl -{ - using type = E; -}; - -} // namespace detail - -template using mp_if_c = typename detail::mp_if_c_impl::type; -template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; - // mp_valid - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 - -// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 - -namespace detail -{ - -template using void_t = void; - -template class F, class... T> -struct mp_valid_impl: mp_false {}; - -template class F, class... T> -struct mp_valid_impl>, F, T...>: mp_true {}; - -} // namespace detail - -template class F, class... T> using mp_valid = typename detail::mp_valid_impl; - -#else - -// implementation by Bruno Dutra (by the name is_evaluable) -namespace detail -{ - -template class F, class... T> struct mp_valid_impl -{ - template class G, class = G> static mp_true check(int); - template class> static mp_false check(...); - - using type = decltype(check(0)); -}; - -} // namespace detail - -template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; - -#endif - -template using mp_valid_q = mp_valid; - // mp_defer -namespace detail -{ - -template class F, class... T> struct mp_defer_impl -{ - using type = F; -}; - -struct mp_no_type -{ -}; - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) - -template class F, class... T> struct mp_defer_cuda_workaround -{ - using type = mp_if, detail::mp_defer_impl, detail::mp_no_type>; -}; - -#endif - -} // namespace detail - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) - -template class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; - -#else - -template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; - -#endif +// moved to detail/mp_defer.hpp // mp_eval_if, mp_eval_if_c namespace detail diff --git a/boost/mp11/version.hpp b/boost/mp11/version.hpp index 318ca01..0912665 100644 --- a/boost/mp11/version.hpp +++ b/boost/mp11/version.hpp @@ -11,6 +11,6 @@ // Same format as BOOST_VERSION: // major * 100000 + minor * 100 + patch -#define BOOST_MP11_VERSION 108200 +#define BOOST_MP11_VERSION 108300 #endif // #ifndef BOOST_MP11_VERSION_HPP_INCLUDED diff --git a/boost/mpl/O1_size.hpp b/boost/mpl/O1_size.hpp deleted file mode 100644 index 98bd3a7..0000000 --- a/boost/mpl/O1_size.hpp +++ /dev/null @@ -1,40 +0,0 @@ - -#ifndef BOOST_MPL_O1_SIZE_HPP_INCLUDED -#define BOOST_MPL_O1_SIZE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// returns sequence size if it's an O(1) operation; otherwise returns -1 -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct O1_size - : O1_size_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, O1_size, (Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, O1_size) - -}} - -#endif // BOOST_MPL_O1_SIZE_HPP_INCLUDED diff --git a/boost/mpl/O1_size_fwd.hpp b/boost/mpl/O1_size_fwd.hpp deleted file mode 100644 index c84a7a5..0000000 --- a/boost/mpl/O1_size_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED -#define BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct O1_size_impl; -template< typename Sequence > struct O1_size; - -}} - -#endif // BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED diff --git a/boost/mpl/advance.hpp b/boost/mpl/advance.hpp deleted file mode 100644 index 1af6004..0000000 --- a/boost/mpl/advance.hpp +++ /dev/null @@ -1,76 +0,0 @@ - -#ifndef BOOST_MPL_ADVANCE_HPP_INCLUDED -#define BOOST_MPL_ADVANCE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation for forward/bidirectional iterators -template< typename Tag > -struct advance_impl -{ - template< typename Iterator, typename N > struct apply - { - typedef typename less< N,long_<0> >::type backward_; - typedef typename if_< backward_, negate, N >::type offset_; - - typedef typename if_< - backward_ - , aux::advance_backward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value > - , aux::advance_forward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value > - >::type f_; - - typedef typename apply_wrap1::type type; - }; -}; - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Iterator) - , typename BOOST_MPL_AUX_NA_PARAM(N) - > -struct advance - : advance_impl< typename tag::type > - ::template apply -{ -}; - -template< - typename Iterator - , BOOST_MPL_AUX_NTTP_DECL(long, N) - > -struct advance_c - : advance_impl< typename tag::type > - ::template apply > -{ -}; - -BOOST_MPL_AUX_NA_SPEC(2, advance) - -}} - -#endif // BOOST_MPL_ADVANCE_HPP_INCLUDED diff --git a/boost/mpl/advance_fwd.hpp b/boost/mpl/advance_fwd.hpp deleted file mode 100644 index 8038410..0000000 --- a/boost/mpl/advance_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED -#define BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -namespace boost { namespace mpl { - -BOOST_MPL_AUX_COMMON_NAME_WKND(advance) - -template< typename Tag > struct advance_impl; -template< typename Iterator, typename N > struct advance; - -}} - -#endif // BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED diff --git a/boost/mpl/assert.hpp b/boost/mpl/assert.hpp index 67700ab..c7ecddf 100644 --- a/boost/mpl/assert.hpp +++ b/boost/mpl/assert.hpp @@ -297,7 +297,7 @@ BOOST_MPL_AUX_ASSERT_CONSTANT( \ std::size_t \ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ boost::mpl::assertion_failed( \ - boost::mpl::assert_arg( (void (*) pred)0, 1 ) \ + boost::mpl::assert_arg( (void (*) pred)BOOST_NULLPTR, 1 ) \ ) \ ) \ ) \ @@ -310,7 +310,7 @@ BOOST_MPL_AUX_ASSERT_CONSTANT( \ enum { \ BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ boost::mpl::assertion::failed( \ - boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \ + boost::mpl::assert_not_arg( (void (*) pred)BOOST_NULLPTR, 1 ) \ ) \ ) \ }\ @@ -321,7 +321,7 @@ BOOST_MPL_AUX_ASSERT_CONSTANT( \ std::size_t \ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \ boost::mpl::assertion_failed( \ - boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \ + boost::mpl::assert_not_arg( (void (*) pred)BOOST_NULLPTR, 1 ) \ ) \ ) \ ) \ diff --git a/boost/mpl/aux_/O1_size_impl.hpp b/boost/mpl/aux_/O1_size_impl.hpp deleted file mode 100644 index 3bcbd0f..0000000 --- a/boost/mpl/aux_/O1_size_impl.hpp +++ /dev/null @@ -1,87 +0,0 @@ - -#ifndef BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED -#define BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation - returns 'Sequence::size' if sequence has a 'size' -// member, and -1 otherwise; conrete sequences might override it by -// specializing either the 'O1_size_impl' or the primary 'O1_size' template - -# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ - && !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) - -namespace aux { -template< typename Sequence > struct O1_size_impl - : Sequence::size -{ -}; -} - -template< typename Tag > -struct O1_size_impl -{ - template< typename Sequence > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : if_< - aux::has_size - , aux::O1_size_impl - , long_<-1> - >::type - { -#else - { - typedef typename if_< - aux::has_size - , aux::O1_size_impl - , long_<-1> - >::type type; - - BOOST_STATIC_CONSTANT(long, value = - (if_< - aux::has_size - , aux::O1_size_impl - , long_<-1> - >::type::value) - ); -#endif - }; -}; - -# else // BOOST_MSVC - -template< typename Tag > -struct O1_size_impl -{ - template< typename Sequence > struct apply - : long_<-1> - { - }; -}; - -# endif - -}} - -#endif // BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/advance_backward.hpp b/boost/mpl/aux_/advance_backward.hpp deleted file mode 100644 index df56793..0000000 --- a/boost/mpl/aux_/advance_backward.hpp +++ /dev/null @@ -1,128 +0,0 @@ - -#if !defined(BOOST_PP_IS_ITERATING) - -///// header body - -#ifndef BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED -#define BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER advance_backward.hpp -# include - -#else - -# include -# include -# include - -# include -# include -# include - -namespace boost { namespace mpl { namespace aux { - -// forward declaration -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_backward; - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > -struct advance_backward -{ - template< typename Iterator > struct apply - { - typedef typename apply_wrap1< - advance_backward - , Iterator - >::type chunk_result_; - - typedef typename apply_wrap1< - advance_backward<( - (N - BOOST_MPL_LIMIT_UNROLLING) < 0 - ? 0 - : N - BOOST_MPL_LIMIT_UNROLLING - )> - , chunk_result_ - >::type type; - }; -}; - -}}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED - -///// iteration, depth == 1 - -// For gcc 4.4 compatability, we must include the -// BOOST_PP_ITERATION_DEPTH test inside an #else clause. -#else // BOOST_PP_IS_ITERATING -#if BOOST_PP_ITERATION_DEPTH() == 1 -#define i_ BOOST_PP_FRAME_ITERATION(1) - -template<> -struct advance_backward< BOOST_PP_FRAME_ITERATION(1) > -{ - template< typename Iterator > struct apply - { - typedef Iterator iter0; - -#if i_ > 0 -# define BOOST_PP_ITERATION_PARAMS_2 \ - (3,(1, BOOST_PP_FRAME_ITERATION(1), )) -# include BOOST_PP_ITERATE() -#endif - - typedef BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(1)) type; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct apply - { - typedef int type; - }; -#endif -}; - -#undef i_ - -///// iteration, depth == 2 - -#elif BOOST_PP_ITERATION_DEPTH() == 2 - -# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2))) -# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2)) - - typedef typename prior::type AUX778076_ITER_1; - -# undef AUX778076_ITER_1 -# undef AUX778076_ITER_0 - -#endif // BOOST_PP_ITERATION_DEPTH() -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/advance_forward.hpp b/boost/mpl/aux_/advance_forward.hpp deleted file mode 100644 index 62b0101..0000000 --- a/boost/mpl/aux_/advance_forward.hpp +++ /dev/null @@ -1,127 +0,0 @@ - -#if !defined(BOOST_PP_IS_ITERATING) - -///// header body - -#ifndef BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED -#define BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER advance_forward.hpp -# include - -#else - -# include -# include -# include - -# include -# include -# include - -namespace boost { namespace mpl { namespace aux { - -// forward declaration -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_forward; - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > -struct advance_forward -{ - template< typename Iterator > struct apply - { - typedef typename apply_wrap1< - advance_forward - , Iterator - >::type chunk_result_; - - typedef typename apply_wrap1< - advance_forward<( - (N - BOOST_MPL_LIMIT_UNROLLING) < 0 - ? 0 - : N - BOOST_MPL_LIMIT_UNROLLING - )> - , chunk_result_ - >::type type; - }; -}; - -}}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED - -///// iteration, depth == 1 - -// For gcc 4.4 compatability, we must include the -// BOOST_PP_ITERATION_DEPTH test inside an #else clause. -#else // BOOST_PP_IS_ITERATING -#if BOOST_PP_ITERATION_DEPTH() == 1 -#define i_ BOOST_PP_FRAME_ITERATION(1) - -template<> -struct advance_forward< BOOST_PP_FRAME_ITERATION(1) > -{ - template< typename Iterator > struct apply - { - typedef Iterator iter0; - -#if i_ > 0 -# define BOOST_PP_ITERATION_PARAMS_2 \ - (3,(1, i_, )) -# include BOOST_PP_ITERATE() -#endif - typedef BOOST_PP_CAT(iter,i_) type; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct apply - { - typedef int type; - }; -#endif -}; - -#undef i_ - -///// iteration, depth == 2 - -#elif BOOST_PP_ITERATION_DEPTH() == 2 - -# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2))) -# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2)) - - typedef typename next::type AUX778076_ITER_1; - -# undef AUX778076_ITER_1 -# undef AUX778076_ITER_0 - -#endif // BOOST_PP_ITERATION_DEPTH() -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/begin_end_impl.hpp b/boost/mpl/aux_/begin_end_impl.hpp deleted file mode 100644 index 58b70dd..0000000 --- a/boost/mpl/aux_/begin_end_impl.hpp +++ /dev/null @@ -1,101 +0,0 @@ - -#ifndef BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - - -namespace aux { - -template< typename Sequence > -struct begin_type -{ - typedef typename Sequence::begin type; -}; -template< typename Sequence > -struct end_type -{ - typedef typename Sequence::end type; -}; - -} - -// default implementation; conrete sequences might override it by -// specializing either the 'begin_impl/end_impl' or the primary -// 'begin/end' templates - -template< typename Tag > -struct begin_impl -{ - template< typename Sequence > struct apply - { - typedef typename eval_if, - aux::begin_type, void_>::type type; - }; -}; - -template< typename Tag > -struct end_impl -{ - template< typename Sequence > struct apply - { - typedef typename eval_if, - aux::end_type, void_>::type type; - }; -}; - -// specialize 'begin_trait/end_trait' for two pre-defined tags - -# define AUX778076_IMPL_SPEC(name, tag, result) \ -template<> \ -struct name##_impl \ -{ \ - template< typename Sequence > struct apply \ - { \ - typedef result type; \ - }; \ -}; \ -/**/ - -// a sequence with nested 'begin/end' typedefs; just query them -AUX778076_IMPL_SPEC(begin, nested_begin_end_tag, typename Sequence::begin) -AUX778076_IMPL_SPEC(end, nested_begin_end_tag, typename Sequence::end) - -// if a type 'T' does not contain 'begin/end' or 'tag' members -// and doesn't specialize either 'begin/end' or 'begin_impl/end_impl' -// templates, then we end up here -AUX778076_IMPL_SPEC(begin, non_sequence_tag, void_) -AUX778076_IMPL_SPEC(end, non_sequence_tag, void_) -AUX778076_IMPL_SPEC(begin, na, void_) -AUX778076_IMPL_SPEC(end, na, void_) - -# undef AUX778076_IMPL_SPEC - - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,begin_impl) -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,end_impl) - -}} - -#endif // BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/clear_impl.hpp b/boost/mpl/aux_/clear_impl.hpp deleted file mode 100644 index 20b270c..0000000 --- a/boost/mpl/aux_/clear_impl.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -// no default implementation; the definition is needed to make MSVC happy - -template< typename Tag > -struct clear_impl -{ - template< typename Sequence > struct apply; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, clear_impl) - -}} - -#endif // BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/empty_impl.hpp b/boost/mpl/aux_/empty_impl.hpp deleted file mode 100644 index cfe55ae..0000000 --- a/boost/mpl/aux_/empty_impl.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation; conrete sequences might override it by -// specializing either the 'empty_impl' or the primary 'empty' template - -template< typename Tag > -struct empty_impl -{ - template< typename Sequence > struct apply - : is_same< - typename begin::type - , typename end::type - > - { - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1,empty_impl) - -}} - -#endif // BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/find_if_pred.hpp b/boost/mpl/aux_/find_if_pred.hpp deleted file mode 100644 index c07d89d..0000000 --- a/boost/mpl/aux_/find_if_pred.hpp +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED -#define BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// Copyright Eric Friedman 2002 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -#include -#include - -namespace boost { namespace mpl { namespace aux { - -template< typename Predicate > -struct find_if_pred -{ - template< typename Iterator > - struct apply - { - typedef not_< aux::iter_apply1 > type; - }; -}; - -}}} - -#endif // BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED diff --git a/boost/mpl/aux_/fold_impl.hpp b/boost/mpl/aux_/fold_impl.hpp deleted file mode 100644 index 97c88c5..0000000 --- a/boost/mpl/aux_/fold_impl.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -# include -# include -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -# include -# include -# endif -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER fold_impl.hpp -# include - -#else - -# define AUX778076_FOLD_IMPL_OP(iter) typename deref::type -# define AUX778076_FOLD_IMPL_NAME_PREFIX fold -# include - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/fold_impl_body.hpp b/boost/mpl/aux_/fold_impl_body.hpp deleted file mode 100644 index c5e1660..0000000 --- a/boost/mpl/aux_/fold_impl_body.hpp +++ /dev/null @@ -1,365 +0,0 @@ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION - -#if !defined(BOOST_PP_IS_ITERATING) - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -# include -# include -# include -# include -# include -# include - -# include -# include -# include - -// local macros, #undef-ined at the end of the header - -# define AUX778076_ITER_FOLD_STEP(unused, i, unused2) \ - typedef typename apply2< \ - ForwardOp \ - , BOOST_PP_CAT(state,i) \ - , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,i)) \ - >::type BOOST_PP_CAT(state,BOOST_PP_INC(i)); \ - typedef typename mpl::next::type \ - BOOST_PP_CAT(iter,BOOST_PP_INC(i)); \ - /**/ - -# define AUX778076_FOLD_IMPL_NAME \ - BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_impl) \ - /**/ - -# define AUX778076_FOLD_CHUNK_NAME \ - BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_chunk) \ - /**/ - -namespace boost { namespace mpl { namespace aux { - -/// forward declaration -template< - BOOST_MPL_AUX_NTTP_DECL(int, N) - , typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME; - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -# if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< - BOOST_MPL_AUX_NTTP_DECL(int, N) - , typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef AUX778076_FOLD_IMPL_NAME< - BOOST_MPL_LIMIT_UNROLLING - , First - , Last - , State - , ForwardOp - > chunk_; - - typedef AUX778076_FOLD_IMPL_NAME< - ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) - , typename chunk_::iterator - , Last - , typename chunk_::state - , ForwardOp - > res_; - - typedef typename res_::state state; - typedef typename res_::iterator iterator; -}; - -// fallback implementation for sequences of unknown size -template< - typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME<-1,First,Last,State,ForwardOp> - : AUX778076_FOLD_IMPL_NAME< - -1 - , typename mpl::next::type - , Last - , typename apply2::type - , ForwardOp - > -{ -}; - -template< - typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME<-1,Last,Last,State,ForwardOp> -{ - typedef State state; - typedef Last iterator; -}; - -# else // BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) - -// Borland have some serious problems with the unrolled version, so -// we always use a basic implementation -template< - BOOST_MPL_AUX_NTTP_DECL(int, N) - , typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef AUX778076_FOLD_IMPL_NAME< - -1 - , typename mpl::next::type - , Last - , typename apply2::type - , ForwardOp - > res_; - - typedef typename res_::state state; - typedef typename res_::iterator iterator; - typedef state type; -}; - -template< - BOOST_MPL_AUX_NTTP_DECL(int, N) - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef State state; - typedef Last iterator; - typedef state type; -}; - -# endif // BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -template< BOOST_MPL_AUX_NTTP_DECL(int, N) > -struct AUX778076_FOLD_CHUNK_NAME; - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< BOOST_MPL_AUX_NTTP_DECL(int, N) > -struct AUX778076_FOLD_CHUNK_NAME -{ - template< - typename First - , typename Last - , typename State - , typename ForwardOp - > - struct result_ - { - typedef AUX778076_FOLD_IMPL_NAME< - BOOST_MPL_LIMIT_UNROLLING - , First - , Last - , State - , ForwardOp - > chunk_; - - typedef AUX778076_FOLD_IMPL_NAME< - ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) - , typename chunk_::iterator - , Last - , typename chunk_::state - , ForwardOp - > res_; - - typedef typename res_::state state; - typedef typename res_::iterator iterator; - }; -}; - -// fallback implementation for sequences of unknown size -template< - typename First - , typename Last - , typename State - , typename ForwardOp - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step); - -template< - typename Last - , typename State - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) -{ - typedef Last iterator; - typedef State state; -}; - -template<> -struct AUX778076_FOLD_CHUNK_NAME<-1> -{ - template< - typename First - , typename Last - , typename State - , typename ForwardOp - > - struct result_ - { - typedef typename if_< - typename is_same::type - , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) - , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) - >::type res_; - - typedef typename res_::state state; - typedef typename res_::iterator iterator; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct result_ - { - typedef int state; - typedef int iterator; - }; -#endif -}; - -template< - typename First - , typename Last - , typename State - , typename ForwardOp - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) -{ - // can't inherit here - it breaks MSVC 7.0 - typedef AUX778076_FOLD_CHUNK_NAME<-1>::template result_< - typename mpl::next::type - , Last - , typename apply2::type - , ForwardOp - > chunk_; - - typedef typename chunk_::state state; - typedef typename chunk_::iterator iterator; -}; - -template< - BOOST_MPL_AUX_NTTP_DECL(int, N) - , typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME - : AUX778076_FOLD_CHUNK_NAME - ::template result_ -{ -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -}}} - -# undef AUX778076_FOLD_IMPL_NAME -# undef AUX778076_FOLD_CHUNK_NAME -# undef AUX778076_ITER_FOLD_STEP - -#undef AUX778076_FOLD_IMPL_OP -#undef AUX778076_FOLD_IMPL_NAME_PREFIX - -///// iteration - -#else - -# define n_ BOOST_PP_FRAME_ITERATION(1) - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -template< - typename First - , typename Last - , typename State - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef First iter0; - typedef State state0; - - BOOST_MPL_PP_REPEAT(n_, AUX778076_ITER_FOLD_STEP, unused) - - typedef BOOST_PP_CAT(state,n_) state; - typedef BOOST_PP_CAT(iter,n_) iterator; -}; - -#else - -template<> struct AUX778076_FOLD_CHUNK_NAME -{ - template< - typename First - , typename Last - , typename State - , typename ForwardOp - > - struct result_ - { - typedef First iter0; - typedef State state0; - - BOOST_MPL_PP_REPEAT(n_, AUX778076_ITER_FOLD_STEP, unused) - - typedef BOOST_PP_CAT(state,n_) state; - typedef BOOST_PP_CAT(iter,n_) iterator; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct result_ - { - typedef int state; - typedef int iterator; - }; -#endif -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -# undef n_ - -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/front_impl.hpp b/boost/mpl/aux_/front_impl.hpp deleted file mode 100644 index 9493c1c..0000000 --- a/boost/mpl/aux_/front_impl.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation; conrete sequences might override it by -// specializing either the 'front_impl' or the primary 'front' template - -template< typename Tag > -struct front_impl -{ - template< typename Sequence > struct apply - { - typedef typename begin::type iter_; - typedef typename deref::type type; - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1,front_impl) - -}} - -#endif // BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/has_begin.hpp b/boost/mpl/aux_/has_begin.hpp deleted file mode 100644 index 4ee415c..0000000 --- a/boost/mpl/aux_/has_begin.hpp +++ /dev/null @@ -1,23 +0,0 @@ - -#ifndef BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED -#define BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -namespace boost { namespace mpl { namespace aux { -BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_begin, begin, true) -}}} - -#endif // BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED diff --git a/boost/mpl/aux_/has_size.hpp b/boost/mpl/aux_/has_size.hpp deleted file mode 100644 index ff29913..0000000 --- a/boost/mpl/aux_/has_size.hpp +++ /dev/null @@ -1,23 +0,0 @@ - -#ifndef BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED -#define BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -namespace boost { namespace mpl { namespace aux { -BOOST_MPL_HAS_XXX_TRAIT_DEF(size) -}}} - -#endif // BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED diff --git a/boost/mpl/aux_/insert_impl.hpp b/boost/mpl/aux_/insert_impl.hpp deleted file mode 100644 index 03a304b..0000000 --- a/boost/mpl/aux_/insert_impl.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -#ifndef BOOST_MPL_INSERT_IMPL_HPP_INCLUDED -#define BOOST_MPL_INSERT_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation; conrete sequences might override it by -// specializing either the 'insert_impl' or the primary 'insert' template - -template< typename Tag > -struct insert_impl -{ - template< - typename Sequence - , typename Pos - , typename T - > - struct apply - { - typedef iterator_range< - typename begin::type - , Pos - > first_half_; - - typedef iterator_range< - Pos - , typename end::type - > second_half_; - - typedef typename reverse_fold< - second_half_ - , typename clear::type - , push_front<_,_> - >::type half_sequence_; - - typedef typename reverse_fold< - first_half_ - , typename push_front::type - , push_front<_,_> - >::type type; - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(3,insert_impl) - -}} - -#endif // BOOST_MPL_INSERT_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/insert_range_impl.hpp b/boost/mpl/aux_/insert_range_impl.hpp deleted file mode 100644 index fa43315..0000000 --- a/boost/mpl/aux_/insert_range_impl.hpp +++ /dev/null @@ -1,80 +0,0 @@ - -#ifndef BOOST_MPL_AUX_INSERT_RANGE_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_INSERT_RANGE_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -// default implementation; conrete sequences might override it by -// specializing either the 'insert_range_impl' or the primary -// 'insert_range' template - - -template< typename Tag > -struct insert_range_impl -{ - template< - typename Sequence - , typename Pos - , typename Range - > - struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : reverse_fold< - joint_view< - iterator_range::type,Pos> - , joint_view< - Range - , iterator_range::type> - > - > - , typename clear::type - , insert<_1, begin<_1>, _2> - > - { -#else - { - typedef typename reverse_fold< - joint_view< - iterator_range::type,Pos> - , joint_view< - Range - , iterator_range::type> - > - > - , typename clear::type - , insert<_1, begin<_1>, _2> - >::type type; -#endif - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(3,insert_range_impl) - -}} - -#endif // BOOST_MPL_AUX_INSERT_RANGE_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/inserter_algorithm.hpp b/boost/mpl/aux_/inserter_algorithm.hpp deleted file mode 100644 index 20ae816..0000000 --- a/boost/mpl/aux_/inserter_algorithm.hpp +++ /dev/null @@ -1,159 +0,0 @@ - -#ifndef BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED -#define BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2003-2004 -// Copyright David Abrahams 2003-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \ -BOOST_MPL_AUX_COMMON_NAME_WKND(name) \ -template< \ - BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ - > \ -struct name \ - : aux::name##_impl \ -{ \ -}; \ -\ -template< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ - > \ -struct name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \ - : if_< has_push_back< typename clear::type> \ - , aux::name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , back_inserter< typename clear::type > \ - > \ - , aux::reverse_##name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , front_inserter< typename clear::type > \ - > \ - >::type \ -{ \ -}; \ -\ -template< \ - BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ - > \ -struct reverse_##name \ - : aux::reverse_##name##_impl \ -{ \ -}; \ -\ -template< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ - > \ -struct reverse_##name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \ - : if_< has_push_back \ - , aux::reverse_##name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , back_inserter< typename clear::type > \ - > \ - , aux::name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , front_inserter< typename clear::type > \ - > \ - >::type \ -{ \ -}; \ -BOOST_MPL_AUX_NA_SPEC(arity, name) \ -BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \ -/**/ - -#else - -# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \ -BOOST_MPL_AUX_COMMON_NAME_WKND(name) \ -template< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ - > \ -struct def_##name##_impl \ - : if_< has_push_back \ - , aux::name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , back_inserter< typename clear::type > \ - > \ - , aux::reverse_##name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , front_inserter< typename clear::type > \ - > \ - >::type \ -{ \ -}; \ -\ -template< \ - BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ - > \ -struct name \ -{ \ - typedef typename eval_if< \ - is_na \ - , def_##name##_impl \ - , aux::name##_impl \ - >::type type; \ -}; \ -\ -template< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ - > \ -struct def_reverse_##name##_impl \ - : if_< has_push_back \ - , aux::reverse_##name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , back_inserter< typename clear::type > \ - > \ - , aux::name##_impl< \ - BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ - , front_inserter< typename clear::type > \ - > \ - >::type \ -{ \ -}; \ -template< \ - BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ - > \ -struct reverse_##name \ -{ \ - typedef typename eval_if< \ - is_na \ - , def_reverse_##name##_impl \ - , aux::reverse_##name##_impl \ - >::type type; \ -}; \ -BOOST_MPL_AUX_NA_SPEC(arity, name) \ -BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \ -/**/ - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#endif // BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED diff --git a/boost/mpl/aux_/iter_apply.hpp b/boost/mpl/aux_/iter_apply.hpp deleted file mode 100644 index 41dfdfa..0000000 --- a/boost/mpl/aux_/iter_apply.hpp +++ /dev/null @@ -1,47 +0,0 @@ - -#ifndef BOOST_MPL_ITER_APPLY_HPP_INCLUDED -#define BOOST_MPL_ITER_APPLY_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { namespace aux { - -template< - typename F - , typename Iterator - > -struct iter_apply1 - : apply1< F,typename deref::type > -{ -}; - -template< - typename F - , typename Iterator1 - , typename Iterator2 - > -struct iter_apply2 - : apply2< - F - , typename deref::type - , typename deref::type - > -{ -}; - -}}} - -#endif // BOOST_MPL_ITER_APPLY_HPP_INCLUDED diff --git a/boost/mpl/aux_/iter_fold_if_impl.hpp b/boost/mpl/aux_/iter_fold_if_impl.hpp deleted file mode 100644 index 6372e83..0000000 --- a/boost/mpl/aux_/iter_fold_if_impl.hpp +++ /dev/null @@ -1,210 +0,0 @@ - -#ifndef BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// Copyright David Abrahams 2001-2002 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -# include -# include -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER iter_fold_if_impl.hpp -# include - -#else - -# include -# include -# include -# include -# include -# include - -namespace boost { namespace mpl { namespace aux { - -template< typename Iterator, typename State > -struct iter_fold_if_null_step -{ - typedef State state; - typedef Iterator iterator; -}; - -template< bool > -struct iter_fold_if_step_impl -{ - template< - typename Iterator - , typename State - , typename StateOp - , typename IteratorOp - > - struct result_ - { - typedef typename apply2::type state; - typedef typename IteratorOp::type iterator; - }; -}; - -template<> -struct iter_fold_if_step_impl -{ - template< - typename Iterator - , typename State - , typename StateOp - , typename IteratorOp - > - struct result_ - { - typedef State state; - typedef Iterator iterator; - }; -}; - -// agurt, 25/jun/02: MSVC 6.5 workaround, had to get rid of inheritance -// here and in 'iter_fold_if_backward_step', because sometimes it interfered -// with the "early template instantiation bug" in _really_ ugly ways -template< - typename Iterator - , typename State - , typename ForwardOp - , typename Predicate - > -struct iter_fold_if_forward_step -{ - typedef typename apply2::type not_last; - typedef typename iter_fold_if_step_impl< - BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value - >::template result_< Iterator,State,ForwardOp,mpl::next > impl_; - - typedef typename impl_::state state; - typedef typename impl_::iterator iterator; -}; - -template< - typename Iterator - , typename State - , typename BackwardOp - , typename Predicate - > -struct iter_fold_if_backward_step -{ - typedef typename apply2::type not_last; - typedef typename iter_fold_if_step_impl< - BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value - >::template result_< Iterator,State,BackwardOp,identity > impl_; - - typedef typename impl_::state state; - typedef typename impl_::iterator iterator; -}; - - -// local macros, #undef-ined at the end of the header - -# define AUX_ITER_FOLD_FORWARD_STEP(unused, i, unused2) \ - typedef iter_fold_if_forward_step< \ - typename BOOST_PP_CAT(forward_step,i)::iterator \ - , typename BOOST_PP_CAT(forward_step,i)::state \ - , ForwardOp \ - , ForwardPredicate \ - > BOOST_PP_CAT(forward_step, BOOST_PP_INC(i)); \ - /**/ - -# define AUX_ITER_FOLD_BACKWARD_STEP_FUNC(i) \ - typedef iter_fold_if_backward_step< \ - typename BOOST_PP_CAT(forward_step,BOOST_PP_DEC(i))::iterator \ - , typename BOOST_PP_CAT(backward_step,i)::state \ - , BackwardOp \ - , BackwardPredicate \ - > BOOST_PP_CAT(backward_step,BOOST_PP_DEC(i)); \ - /**/ - -# define AUX_ITER_FOLD_BACKWARD_STEP(unused, i, unused2) \ - AUX_ITER_FOLD_BACKWARD_STEP_FUNC( \ - BOOST_PP_SUB_D(1,BOOST_MPL_LIMIT_UNROLLING,i) \ - ) \ - /**/ - -# define AUX_LAST_FORWARD_STEP \ - BOOST_PP_CAT(forward_step, BOOST_MPL_LIMIT_UNROLLING) \ - /**/ - -# define AUX_LAST_BACKWARD_STEP \ - BOOST_PP_CAT(backward_step, BOOST_MPL_LIMIT_UNROLLING) \ - /**/ - -template< - typename Iterator - , typename State - , typename ForwardOp - , typename ForwardPredicate - , typename BackwardOp - , typename BackwardPredicate - > -struct iter_fold_if_impl -{ - private: - typedef iter_fold_if_null_step forward_step0; - BOOST_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX_ITER_FOLD_FORWARD_STEP - , unused - ) - - typedef typename if_< - typename AUX_LAST_FORWARD_STEP::not_last - , iter_fold_if_impl< - typename AUX_LAST_FORWARD_STEP::iterator - , typename AUX_LAST_FORWARD_STEP::state - , ForwardOp - , ForwardPredicate - , BackwardOp - , BackwardPredicate - > - , iter_fold_if_null_step< - typename AUX_LAST_FORWARD_STEP::iterator - , typename AUX_LAST_FORWARD_STEP::state - > - >::type AUX_LAST_BACKWARD_STEP; - - BOOST_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX_ITER_FOLD_BACKWARD_STEP - , unused - ) - - public: - typedef typename backward_step0::state state; - typedef typename AUX_LAST_BACKWARD_STEP::iterator iterator; -}; - -# undef AUX_LAST_BACKWARD_STEP -# undef AUX_LAST_FORWARD_STEP -# undef AUX_ITER_FOLD_BACKWARD_STEP -# undef AUX_ITER_FOLD_BACKWARD_STEP_FUNC -# undef AUX_ITER_FOLD_FORWARD_STEP - -}}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/iter_fold_impl.hpp b/boost/mpl/aux_/iter_fold_impl.hpp deleted file mode 100644 index b4d2922..0000000 --- a/boost/mpl/aux_/iter_fold_impl.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -# include -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -# include -# include -# endif -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER iter_fold_impl.hpp -# include - -#else - -# define AUX778076_FOLD_IMPL_OP(iter) iter -# define AUX778076_FOLD_IMPL_NAME_PREFIX iter_fold -# include - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/iter_push_front.hpp b/boost/mpl/aux_/iter_push_front.hpp deleted file mode 100644 index 35ccc4d..0000000 --- a/boost/mpl/aux_/iter_push_front.hpp +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef BOOST_MPL_ITER_PUSH_FRONT_HPP_INCLUDED -#define BOOST_MPL_ITER_PUSH_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { namespace aux { - -template< - typename Sequence - , typename Iterator - > -struct iter_push_front -{ - typedef typename push_front< - Sequence - , typename deref::type - >::type type; -}; - -}}} - -#endif // BOOST_MPL_ITER_PUSH_FRONT_HPP_INCLUDED diff --git a/boost/mpl/aux_/joint_iter.hpp b/boost/mpl/aux_/joint_iter.hpp deleted file mode 100644 index 277580e..0000000 --- a/boost/mpl/aux_/joint_iter.hpp +++ /dev/null @@ -1,120 +0,0 @@ - -#ifndef BOOST_MPL_AUX_JOINT_ITER_HPP_INCLUDED -#define BOOST_MPL_AUX_JOINT_ITER_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -# include -#endif - -namespace boost { namespace mpl { - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -template< - typename Iterator1 - , typename LastIterator1 - , typename Iterator2 - > -struct joint_iter -{ - typedef Iterator1 base; - typedef forward_iterator_tag category; -}; - -template< - typename LastIterator1 - , typename Iterator2 - > -struct joint_iter -{ - typedef Iterator2 base; - typedef forward_iterator_tag category; -}; - - -template< typename I1, typename L1, typename I2 > -struct deref< joint_iter > -{ - typedef typename joint_iter::base base_; - typedef typename deref::type type; -}; - -template< typename I1, typename L1, typename I2 > -struct next< joint_iter > -{ - typedef joint_iter< typename mpl::next::type,L1,I2 > type; -}; - -template< typename L1, typename I2 > -struct next< joint_iter > -{ - typedef joint_iter< L1,L1,typename mpl::next::type > type; -}; - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -template< - typename Iterator1 - , typename LastIterator1 - , typename Iterator2 - > -struct joint_iter; - -template< bool > struct joint_iter_impl -{ - template< typename I1, typename L1, typename I2 > struct result_ - { - typedef I1 base; - typedef forward_iterator_tag category; - typedef joint_iter< typename mpl::next::type,L1,I2 > next; - typedef typename deref::type type; - }; -}; - -template<> struct joint_iter_impl -{ - template< typename I1, typename L1, typename I2 > struct result_ - { - typedef I2 base; - typedef forward_iterator_tag category; - typedef joint_iter< L1,L1,typename mpl::next::type > next; - typedef typename deref::type type; - }; -}; - -template< - typename Iterator1 - , typename LastIterator1 - , typename Iterator2 - > -struct joint_iter - : joint_iter_impl< is_same::value > - ::template result_ -{ -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(3, joint_iter) - -}} - -#endif // BOOST_MPL_AUX_JOINT_ITER_HPP_INCLUDED diff --git a/boost/mpl/aux_/lambda_spec.hpp b/boost/mpl/aux_/lambda_spec.hpp deleted file mode 100644 index 6ffacc0..0000000 --- a/boost/mpl/aux_/lambda_spec.hpp +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED -#define BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2007 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) - -# define BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(i, name) \ -template< \ - BOOST_MPL_PP_PARAMS(i, typename T) \ - , typename Tag \ - > \ -struct lambda< \ - name< BOOST_MPL_PP_PARAMS(i, T) > \ - , Tag \ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(int_) \ - > \ -{ \ - typedef false_ is_le; \ - typedef name< BOOST_MPL_PP_PARAMS(i, T) > result_; \ - typedef result_ type; \ -}; \ -/**/ - -#else - -# define BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(i, name) /**/ - -#endif - -#endif // BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED diff --git a/boost/mpl/aux_/msvc_type.hpp b/boost/mpl/aux_/msvc_type.hpp deleted file mode 100644 index bea244f..0000000 --- a/boost/mpl/aux_/msvc_type.hpp +++ /dev/null @@ -1,62 +0,0 @@ - -#ifndef BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED -#define BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { namespace aux { - -#if defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) - -template< bool > struct msvc_type_impl -{ - template< typename T > struct result_ - { - typedef typename T::type type; - }; -}; - -template<> struct msvc_type_impl -{ - template< typename T > struct result_ - { - typedef result_ type; - }; -}; - -template< typename T > struct msvc_type - : msvc_type_impl< is_msvc_eti_arg::value > - ::template result_ -{ -}; - -#else // BOOST_MPL_CFG_MSVC_70_ETI_BUG - -template< typename T > struct msvc_type -{ - typedef typename T::type type; -}; - -template<> struct msvc_type -{ - typedef int type; -}; - -#endif - -}}} - -#endif // BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED diff --git a/boost/mpl/aux_/push_back_impl.hpp b/boost/mpl/aux_/push_back_impl.hpp deleted file mode 100644 index 27e7a60..0000000 --- a/boost/mpl/aux_/push_back_impl.hpp +++ /dev/null @@ -1,70 +0,0 @@ - -#ifndef BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -struct has_push_back_arg {}; - -// agurt 05/feb/04: no default implementation; the stub definition is needed -// to enable the default 'has_push_back' implementation below -template< typename Tag > -struct push_back_impl -{ - template< typename Sequence, typename T > struct apply - { - // should be instantiated only in the context of 'has_push_back_impl'; - // if you've got an assert here, you are requesting a 'push_back' - // specialization that doesn't exist. - BOOST_MPL_ASSERT_MSG( - ( boost::is_same< T, has_push_back_arg >::value ) - , REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST - , ( Sequence ) - ); - }; -}; - -template< typename Tag > -struct has_push_back_impl -{ - template< typename Seq > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : aux::has_type< push_back< Seq, has_push_back_arg > > - { -#else - { - typedef aux::has_type< push_back< Seq, has_push_back_arg > > type; - BOOST_STATIC_CONSTANT(bool, value = - (aux::has_type< push_back< Seq, has_push_back_arg > >::value) - ); -#endif - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_back_impl) -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_back_impl) - -}} - -#endif // BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/push_front_impl.hpp b/boost/mpl/aux_/push_front_impl.hpp deleted file mode 100644 index 5b83ee7..0000000 --- a/boost/mpl/aux_/push_front_impl.hpp +++ /dev/null @@ -1,71 +0,0 @@ - -#ifndef BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -struct has_push_front_arg {}; - -// agurt 05/feb/04: no default implementation; the stub definition is needed -// to enable the default 'has_push_front' implementation below - -template< typename Tag > -struct push_front_impl -{ - template< typename Sequence, typename T > struct apply - { - // should be instantiated only in the context of 'has_push_front_impl'; - // if you've got an assert here, you are requesting a 'push_front' - // specialization that doesn't exist. - BOOST_MPL_ASSERT_MSG( - ( boost::is_same< T, has_push_front_arg >::value ) - , REQUESTED_PUSH_FRONT_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST - , ( Sequence ) - ); - }; -}; - -template< typename Tag > -struct has_push_front_impl -{ - template< typename Seq > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : aux::has_type< push_front< Seq, has_push_front_arg > > - { -#else - { - typedef aux::has_type< push_front< Seq, has_push_front_arg > > type; - BOOST_STATIC_CONSTANT(bool, value = - (aux::has_type< push_front< Seq, has_push_front_arg > >::value) - ); -#endif - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_front_impl) -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_front_impl) - -}} - -#endif // BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/reverse_fold_impl.hpp b/boost/mpl/aux_/reverse_fold_impl.hpp deleted file mode 100644 index a27a35f..0000000 --- a/boost/mpl/aux_/reverse_fold_impl.hpp +++ /dev/null @@ -1,44 +0,0 @@ - -#ifndef BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -# include -# include -# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ - || defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) -# include -# include -# endif -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER reverse_fold_impl.hpp -# include - -#else - -# define AUX778076_FOLD_IMPL_OP(iter) typename deref::type -# define AUX778076_FOLD_IMPL_NAME_PREFIX reverse_fold -# include - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/reverse_fold_impl_body.hpp b/boost/mpl/aux_/reverse_fold_impl_body.hpp deleted file mode 100644 index 0f80010..0000000 --- a/boost/mpl/aux_/reverse_fold_impl_body.hpp +++ /dev/null @@ -1,412 +0,0 @@ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION! - -#if !defined(BOOST_PP_IS_ITERATING) - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -# include -# include -# include -# include - -# include -# include -# include -# include -# include - -// local macros, #undef-ined at the end of the header - -# define AUX778076_ITER_FOLD_FORWARD_STEP(unused, n_, unused2) \ - typedef typename apply2< \ - ForwardOp \ - , BOOST_PP_CAT(fwd_state,n_) \ - , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,n_)) \ - >::type BOOST_PP_CAT(fwd_state,BOOST_PP_INC(n_)); \ - typedef typename mpl::next::type \ - BOOST_PP_CAT(iter,BOOST_PP_INC(n_)); \ - /**/ - -# define AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC(n_) \ - typedef typename apply2< \ - BackwardOp \ - , BOOST_PP_CAT(bkwd_state,n_) \ - , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,BOOST_PP_DEC(n_))) \ - >::type BOOST_PP_CAT(bkwd_state,BOOST_PP_DEC(n_)); \ - /**/ - -# define AUX778076_ITER_FOLD_BACKWARD_STEP(unused, n_, j) \ - AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC( \ - BOOST_PP_SUB_D(1,j,n_) \ - ) \ - /**/ - -# define AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(n_) \ - typedef typename nested_chunk::state BOOST_PP_CAT(bkwd_state,n_); - /**/ - -# define AUX778076_FOLD_IMPL_NAME \ - BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_impl) \ - /**/ - -# define AUX778076_FOLD_CHUNK_NAME \ - BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_chunk) \ - /**/ - -namespace boost { namespace mpl { namespace aux { - -/// forward declaration -template< - BOOST_MPL_AUX_NTTP_DECL(long, N) - , typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME; - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ - && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< - BOOST_MPL_AUX_NTTP_DECL(long, N) - , typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef First iter0; - typedef State fwd_state0; - - BOOST_MPL_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX778076_ITER_FOLD_FORWARD_STEP - , unused - ) - - typedef AUX778076_FOLD_IMPL_NAME< - ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) - , BOOST_PP_CAT(iter,BOOST_MPL_LIMIT_UNROLLING) - , Last - , BOOST_PP_CAT(fwd_state,BOOST_MPL_LIMIT_UNROLLING) - , BackwardOp - , ForwardOp - > nested_chunk; - - AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(BOOST_MPL_LIMIT_UNROLLING) - - BOOST_MPL_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX778076_ITER_FOLD_BACKWARD_STEP - , BOOST_MPL_LIMIT_UNROLLING - ) - - typedef bkwd_state0 state; - typedef typename nested_chunk::iterator iterator; -}; - -// fallback implementation for sequences of unknown size -template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME<-1,First,Last,State,BackwardOp,ForwardOp> -{ - typedef AUX778076_FOLD_IMPL_NAME< - -1 - , typename mpl::next::type - , Last - , typename apply2::type - , BackwardOp - , ForwardOp - > nested_step; - - typedef typename apply2< - BackwardOp - , typename nested_step::state - , AUX778076_FOLD_IMPL_OP(First) - >::type state; - - typedef typename nested_step::iterator iterator; -}; - -template< - typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME<-1,Last,Last,State,BackwardOp,ForwardOp> -{ - typedef State state; - typedef Last iterator; -}; - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > -struct AUX778076_FOLD_CHUNK_NAME; - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) -# include BOOST_PP_ITERATE() - -// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > -struct AUX778076_FOLD_CHUNK_NAME -{ - template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > - struct result_ - { - typedef First iter0; - typedef State fwd_state0; - - BOOST_MPL_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX778076_ITER_FOLD_FORWARD_STEP - , unused - ) - - typedef AUX778076_FOLD_IMPL_NAME< - ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) - , BOOST_PP_CAT(iter,BOOST_MPL_LIMIT_UNROLLING) - , Last - , BOOST_PP_CAT(fwd_state,BOOST_MPL_LIMIT_UNROLLING) - , BackwardOp - , ForwardOp - > nested_chunk; - - AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(BOOST_MPL_LIMIT_UNROLLING) - - BOOST_MPL_PP_REPEAT( - BOOST_MPL_LIMIT_UNROLLING - , AUX778076_ITER_FOLD_BACKWARD_STEP - , BOOST_MPL_LIMIT_UNROLLING - ) - - typedef bkwd_state0 state; - typedef typename nested_chunk::iterator iterator; - }; -}; - -// fallback implementation for sequences of unknown size -template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step); - -template< - typename Last - , typename State - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) -{ - typedef Last iterator; - typedef State state; -}; - -template<> -struct AUX778076_FOLD_CHUNK_NAME<-1> -{ - template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > - struct result_ - { - typedef typename if_< - typename is_same::type - , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) - , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) - >::type res_; - - typedef typename res_::state state; - typedef typename res_::iterator iterator; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct result_ - { - typedef int state; - typedef int iterator; - }; -#endif -}; - -template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) -{ - typedef AUX778076_FOLD_CHUNK_NAME<-1>::template result_< - typename mpl::next::type - , Last - , typename apply2::type - , BackwardOp - , ForwardOp - > nested_step; - - typedef typename apply2< - BackwardOp - , typename nested_step::state - , AUX778076_FOLD_IMPL_OP(First) - >::type state; - - typedef typename nested_step::iterator iterator; -}; - -template< - BOOST_MPL_AUX_NTTP_DECL(long, N) - , typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME - : AUX778076_FOLD_CHUNK_NAME - ::template result_ -{ -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -}}} - -# undef AUX778076_FIRST_BACKWARD_STATE_TYPEDEF -# undef AUX778076_ITER_FOLD_BACKWARD_STEP -# undef AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC -# undef AUX778076_ITER_FOLD_FORWARD_STEP - -#undef AUX778076_FOLD_IMPL_OP -#undef AUX778076_FOLD_IMPL_NAME_PREFIX - -///// iteration - -#else - -# define n_ BOOST_PP_FRAME_ITERATION(1) - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ - && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) - -template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > -struct AUX778076_FOLD_IMPL_NAME -{ - typedef First iter0; - typedef State fwd_state0; - - BOOST_MPL_PP_REPEAT( - n_ - , AUX778076_ITER_FOLD_FORWARD_STEP - , unused - ) - - typedef BOOST_PP_CAT(fwd_state,n_) BOOST_PP_CAT(bkwd_state,n_); - - BOOST_MPL_PP_REPEAT( - n_ - , AUX778076_ITER_FOLD_BACKWARD_STEP - , n_ - ) - - typedef bkwd_state0 state; - typedef BOOST_PP_CAT(iter,n_) iterator; -}; - -#else - -template<> struct AUX778076_FOLD_CHUNK_NAME -{ - template< - typename First - , typename Last - , typename State - , typename BackwardOp - , typename ForwardOp - > - struct result_ - { - typedef First iter0; - typedef State fwd_state0; - - BOOST_MPL_PP_REPEAT( - n_ - , AUX778076_ITER_FOLD_FORWARD_STEP - , unused - ) - - typedef BOOST_PP_CAT(fwd_state,n_) BOOST_PP_CAT(bkwd_state,n_); - - BOOST_MPL_PP_REPEAT( - n_ - , AUX778076_ITER_FOLD_BACKWARD_STEP - , n_ - ) - - typedef bkwd_state0 state; - typedef BOOST_PP_CAT(iter,n_) iterator; - }; - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) - /// ETI workaround - template<> struct result_ - { - typedef int state; - typedef int iterator; - }; -#endif -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -# undef n_ - -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/sequence_wrapper.hpp b/boost/mpl/aux_/sequence_wrapper.hpp deleted file mode 100644 index 3f5e553..0000000 --- a/boost/mpl/aux_/sequence_wrapper.hpp +++ /dev/null @@ -1,292 +0,0 @@ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION - -#if !defined(BOOST_PP_IS_ITERATING) - -///// header body - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -# include -# include -# include - -# include -# include -# include -# include -# include -# include -# include -# include - -#if defined(BOOST_MPL_PREPROCESSING_MODE) -# undef LONG_MAX -#endif - -namespace boost { namespace mpl { - -#if !defined(AUX778076_SEQUENCE_BASE_NAME) -# define AUX778076_SEQUENCE_BASE_NAME AUX778076_SEQUENCE_NAME -#endif - -#if !defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) - -# define AUX778076_SEQUENCE_PARAM_NAME T -# define AUX778076_SEQUENCE_TEMPLATE_PARAM typename T -# define AUX778076_SEQUENCE_DEFAULT na - -# define AUX778076_SEQUENCE_NAME_N(n) \ - BOOST_PP_CAT(AUX778076_SEQUENCE_BASE_NAME,n) \ - /**/ - -# define AUX778076_SEQUENCE_PARAMS() \ - BOOST_PP_ENUM_PARAMS( \ - AUX778076_SEQUENCE_LIMIT \ - , AUX778076_SEQUENCE_TEMPLATE_PARAM \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_ARGS() \ - BOOST_PP_ENUM_PARAMS( \ - AUX778076_SEQUENCE_LIMIT \ - , T \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_DEFAULT_PARAMS() \ - BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ - AUX778076_SEQUENCE_LIMIT \ - , AUX778076_SEQUENCE_TEMPLATE_PARAM \ - , AUX778076_SEQUENCE_DEFAULT \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_N_PARAMS(n) \ - BOOST_PP_ENUM_PARAMS(n, AUX778076_SEQUENCE_TEMPLATE_PARAM) \ - /**/ - -# define AUX778076_SEQUENCE_N_ARGS(n) \ - BOOST_PP_ENUM_PARAMS(n, T) \ - /**/ - -# define AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(n) \ - BOOST_PP_ENUM_PARAMS(n, T) \ - BOOST_PP_COMMA_IF(n) \ - BOOST_PP_ENUM( \ - BOOST_PP_SUB_D(1,AUX778076_SEQUENCE_LIMIT,n) \ - , BOOST_PP_TUPLE_ELEM_3_2 \ - , AUX778076_SEQUENCE_DEFAULT \ - ) \ - /**/ - -#else // AUX778076_SEQUENCE_INTEGRAL_WRAPPER - -# define AUX778076_SEQUENCE_PARAM_NAME C -# define AUX778076_SEQUENCE_TEMPLATE_PARAM BOOST_MPL_AUX_NTTP_DECL(long, C) -# define AUX778076_SEQUENCE_DEFAULT LONG_MAX - -# define AUX778076_SEQUENCE_PARAMS() \ - typename T, BOOST_PP_ENUM_PARAMS( \ - AUX778076_SEQUENCE_LIMIT \ - , AUX778076_SEQUENCE_TEMPLATE_PARAM \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_ARGS() \ - T, BOOST_PP_ENUM_PARAMS( \ - AUX778076_SEQUENCE_LIMIT \ - , C \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_DEFAULT_PARAMS() \ - typename T, \ - BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ - AUX778076_SEQUENCE_LIMIT \ - , AUX778076_SEQUENCE_TEMPLATE_PARAM \ - , AUX778076_SEQUENCE_DEFAULT \ - ) \ - /**/ - -# define AUX778076_SEQUENCE_N_PARAMS(n) \ - typename T BOOST_PP_COMMA_IF(n) \ - BOOST_PP_ENUM_PARAMS(n, AUX778076_SEQUENCE_TEMPLATE_PARAM) \ - /**/ - -# if !defined(AUX778076_SEQUENCE_CONVERT_CN_TO) -# define AUX778076_SEQUENCE_CONVERT_CN_TO(z,n,TARGET) BOOST_PP_CAT(C,n) -# endif - -# define AUX778076_SEQUENCE_N_ARGS(n) \ - T BOOST_PP_COMMA_IF(n) \ - BOOST_PP_ENUM(n,AUX778076_SEQUENCE_CONVERT_CN_TO,T) \ - /**/ - -# define AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(n) \ - T, BOOST_PP_ENUM_PARAMS(n, C) \ - BOOST_PP_COMMA_IF(n) \ - BOOST_PP_ENUM( \ - BOOST_PP_SUB_D(1,AUX778076_SEQUENCE_LIMIT,n) \ - , BOOST_PP_TUPLE_ELEM_3_2 \ - , AUX778076_SEQUENCE_DEFAULT \ - ) \ - /**/ - -#endif // AUX778076_SEQUENCE_INTEGRAL_WRAPPER - - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) -// forward declaration -template< - AUX778076_SEQUENCE_DEFAULT_PARAMS() - > -struct AUX778076_SEQUENCE_NAME; -#else -namespace aux { -template< BOOST_MPL_AUX_NTTP_DECL(int, N) > -struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser); -} -#endif - -#define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(0, AUX778076_SEQUENCE_LIMIT, )) -#include BOOST_PP_ITERATE() - -// real C++ version is already taken care of -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -namespace aux { -// ???_count_args -#define AUX778076_COUNT_ARGS_PREFIX AUX778076_SEQUENCE_NAME -#define AUX778076_COUNT_ARGS_DEFAULT AUX778076_SEQUENCE_DEFAULT -#define AUX778076_COUNT_ARGS_PARAM_NAME AUX778076_SEQUENCE_PARAM_NAME -#define AUX778076_COUNT_ARGS_TEMPLATE_PARAM AUX778076_SEQUENCE_TEMPLATE_PARAM -#define AUX778076_COUNT_ARGS_ARITY AUX778076_SEQUENCE_LIMIT -#define AUX778076_COUNT_ARGS_USE_STANDARD_PP_PRIMITIVES -#include - -template< - AUX778076_SEQUENCE_PARAMS() - > -struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl) -{ - typedef aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_count_args)< - BOOST_PP_ENUM_PARAMS(AUX778076_SEQUENCE_LIMIT, AUX778076_SEQUENCE_PARAM_NAME) - > arg_num_; - - typedef typename aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser)< arg_num_::value > - ::template result_< AUX778076_SEQUENCE_ARGS() >::type type; -}; - -} // namespace aux - -template< - AUX778076_SEQUENCE_DEFAULT_PARAMS() - > -struct AUX778076_SEQUENCE_NAME - : aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl)< - AUX778076_SEQUENCE_ARGS() - >::type -{ - typedef typename aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl)< - AUX778076_SEQUENCE_ARGS() - >::type type; -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -# undef AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS -# undef AUX778076_SEQUENCE_N_ARGS -# undef AUX778076_SEQUENCE_CONVERT_CN_TO -# undef AUX778076_SEQUENCE_N_PARAMS -# undef AUX778076_SEQUENCE_DEFAULT_PARAMS -# undef AUX778076_SEQUENCE_ARGS -# undef AUX778076_SEQUENCE_PARAMS -# undef AUX778076_SEQUENCE_NAME_N -# undef AUX778076_SEQUENCE_DEFAULT -# undef AUX778076_SEQUENCE_TEMPLATE_PARAM -# undef AUX778076_SEQUENCE_PARAM_NAME -# undef AUX778076_SEQUENCE_LIMIT -# undef AUX778076_SEQUENCE_BASE_NAME -# undef AUX778076_SEQUENCE_NAME -# undef AUX778076_SEQUENCE_INTEGRAL_WRAPPER - -}} - -///// iteration - -#else -#define i_ BOOST_PP_FRAME_ITERATION(1) - -# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -#if i_ == AUX778076_SEQUENCE_LIMIT - -/// primary template (not a specialization!) -template< - AUX778076_SEQUENCE_N_PARAMS(i_) - > -struct AUX778076_SEQUENCE_NAME - : AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) > -{ - typedef typename AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; -}; - -#else - -template< - AUX778076_SEQUENCE_N_PARAMS(i_) - > -struct AUX778076_SEQUENCE_NAME< AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(i_) > - : AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) > -{ -#if i_ > 0 || defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) - typedef typename AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; -#else - typedef AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; -#endif -}; - -#endif // i_ == AUX778076_SEQUENCE_LIMIT - -# else - -namespace aux { - -template<> -struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser) -{ - template< - AUX778076_SEQUENCE_PARAMS() - > - struct result_ - { -#if i_ > 0 || defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) - typedef typename AUX778076_SEQUENCE_NAME_N(i_)< - AUX778076_SEQUENCE_N_ARGS(i_) - >::type type; -#else - typedef AUX778076_SEQUENCE_NAME_N(i_)< - AUX778076_SEQUENCE_N_ARGS(i_) - >::type type; -#endif - }; -}; - -} // namespace aux - -# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -#undef i_ -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/size_impl.hpp b/boost/mpl/aux_/size_impl.hpp deleted file mode 100644 index 21fbe63..0000000 --- a/boost/mpl/aux_/size_impl.hpp +++ /dev/null @@ -1,52 +0,0 @@ - -#ifndef BOOST_MPL_AUX_SIZE_IMPL_HPP_INCLUDED -#define BOOST_MPL_AUX_SIZE_IMPL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// default implementation; conrete sequences might override it by -// specializing either the 'size_impl' or the primary 'size' template - -template< typename Tag > -struct size_impl -{ - template< typename Sequence > struct apply -#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x561)) - : distance< - typename begin::type - , typename end::type - > - { -#else - { - typedef typename distance< - typename begin::type - , typename end::type - >::type type; -#endif - }; -}; - -BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, size_impl) - -}} - -#endif // BOOST_MPL_AUX_SIZE_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/traits_lambda_spec.hpp b/boost/mpl/aux_/traits_lambda_spec.hpp deleted file mode 100644 index 4a7ff26..0000000 --- a/boost/mpl/aux_/traits_lambda_spec.hpp +++ /dev/null @@ -1,63 +0,0 @@ - -#ifndef BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED -#define BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) - -# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) /**/ - -#elif !defined(BOOST_MPL_CFG_MSVC_ETI_BUG) - -# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ -template<> struct trait \ -{ \ - template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ - { \ - }; \ -}; \ -/**/ - -#else - -# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ -template<> struct trait \ -{ \ - template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ - { \ - }; \ -}; \ -template<> struct trait \ -{ \ - template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ - { \ - typedef int type; \ - }; \ -}; \ -/**/ - -#endif // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT - - -#define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(i, trait) \ - BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ - template<> struct trait {}; \ -/**/ - -#endif // BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED diff --git a/boost/mpl/back_inserter.hpp b/boost/mpl/back_inserter.hpp deleted file mode 100644 index 8fc4083..0000000 --- a/boost/mpl/back_inserter.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef BOOST_MPL_BACK_INSERTER_HPP_INCLUDED -#define BOOST_MPL_BACK_INSERTER_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2003-2004 -// Copyright David Abrahams 2003-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { -namespace mpl { - -template< - typename Sequence - > -struct back_inserter - : inserter< Sequence,push_back<> > -{ -}; - -}} - -#endif // BOOST_MPL_BACK_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/begin_end.hpp b/boost/mpl/begin_end.hpp deleted file mode 100644 index b7074af..0000000 --- a/boost/mpl/begin_end.hpp +++ /dev/null @@ -1,57 +0,0 @@ - -#ifndef BOOST_MPL_BEGIN_END_HPP_INCLUDED -#define BOOST_MPL_BEGIN_END_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// agurt, 13/sep/02: switched from inheritance to typedef; MSVC is more -// happy this way (less ETI-related errors), and it doesn't affect -// anything else -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct begin -{ - typedef typename sequence_tag::type tag_; - typedef typename begin_impl< tag_ > - ::template apply< Sequence >::type type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,begin,(Sequence)) -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct end -{ - typedef typename sequence_tag::type tag_; - typedef typename end_impl< tag_ > - ::template apply< Sequence >::type type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,end,(Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, begin) -BOOST_MPL_AUX_NA_SPEC(1, end) - -}} - -#endif // BOOST_MPL_BEGIN_END_HPP_INCLUDED diff --git a/boost/mpl/begin_end_fwd.hpp b/boost/mpl/begin_end_fwd.hpp deleted file mode 100644 index 70ef9ef..0000000 --- a/boost/mpl/begin_end_fwd.hpp +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED -#define BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct begin_impl; -template< typename Tag > struct end_impl; - -template< typename Sequence > struct begin; -template< typename Sequence > struct end; - -}} - -#endif // BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED diff --git a/boost/mpl/clear.hpp b/boost/mpl/clear.hpp deleted file mode 100644 index c6b95ed..0000000 --- a/boost/mpl/clear.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef BOOST_MPL_CLEAR_HPP_INCLUDED -#define BOOST_MPL_CLEAR_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct clear - : clear_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,clear,(Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, clear) - -}} - -#endif // BOOST_MPL_CLEAR_HPP_INCLUDED diff --git a/boost/mpl/clear_fwd.hpp b/boost/mpl/clear_fwd.hpp deleted file mode 100644 index d14a1d2..0000000 --- a/boost/mpl/clear_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_CLEAR_FWD_HPP_INCLUDED -#define BOOST_MPL_CLEAR_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct clear_impl; -template< typename Sequence > struct clear; - -}} - -#endif // BOOST_MPL_CLEAR_FWD_HPP_INCLUDED diff --git a/boost/mpl/deref.hpp b/boost/mpl/deref.hpp deleted file mode 100644 index 1105ec9..0000000 --- a/boost/mpl/deref.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef BOOST_MPL_DEREF_HPP_INCLUDED -#define BOOST_MPL_DEREF_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Iterator) - > -struct deref -{ -#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) - typedef typename Iterator::type type; -#else - typedef typename aux::msvc_type::type type; -#endif - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,deref,(Iterator)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, deref) - -}} - -#endif // BOOST_MPL_DEREF_HPP_INCLUDED diff --git a/boost/mpl/distance.hpp b/boost/mpl/distance.hpp deleted file mode 100644 index 95f4f33..0000000 --- a/boost/mpl/distance.hpp +++ /dev/null @@ -1,78 +0,0 @@ - -#ifndef BOOST_MPL_DISTANCE_HPP_INCLUDED -#define BOOST_MPL_DISTANCE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace boost { namespace mpl { - -// default implementation for forward/bidirectional iterators -template< typename Tag > struct distance_impl -{ - template< typename First, typename Last > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : aux::msvc_eti_base< typename iter_fold< - iterator_range - , mpl::long_<0> - , next<> - >::type > - { -#else - { - typedef typename iter_fold< - iterator_range - , mpl::long_<0> - , next<> - >::type type; - - BOOST_STATIC_CONSTANT(long, value = - (iter_fold< - iterator_range - , mpl::long_<0> - , next<> - >::type::value) - ); -#endif - }; -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(First) - , typename BOOST_MPL_AUX_NA_PARAM(Last) - > -struct distance - : distance_impl< typename tag::type > - ::template apply -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(2, distance, (First, Last)) -}; - -BOOST_MPL_AUX_NA_SPEC(2, distance) - -}} - -#endif // BOOST_MPL_DISTANCE_HPP_INCLUDED diff --git a/boost/mpl/distance_fwd.hpp b/boost/mpl/distance_fwd.hpp deleted file mode 100644 index a69a7c5..0000000 --- a/boost/mpl/distance_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED -#define BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -namespace boost { namespace mpl { - -BOOST_MPL_AUX_COMMON_NAME_WKND(distance) - -template< typename Tag > struct distance_impl; -template< typename First, typename Last > struct distance; - -}} - -#endif // BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED diff --git a/boost/mpl/empty.hpp b/boost/mpl/empty.hpp deleted file mode 100644 index 1185324..0000000 --- a/boost/mpl/empty.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef BOOST_MPL_EMPTY_HPP_INCLUDED -#define BOOST_MPL_EMPTY_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct empty - : empty_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,empty,(Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, empty) - -}} - -#endif // BOOST_MPL_EMPTY_HPP_INCLUDED diff --git a/boost/mpl/empty_fwd.hpp b/boost/mpl/empty_fwd.hpp deleted file mode 100644 index 551c966..0000000 --- a/boost/mpl/empty_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_EMPTY_FWD_HPP_INCLUDED -#define BOOST_MPL_EMPTY_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct empty_impl; -template< typename Sequence > struct empty; - -}} - -#endif // BOOST_MPL_EMPTY_FWD_HPP_INCLUDED diff --git a/boost/mpl/equal.hpp b/boost/mpl/equal.hpp deleted file mode 100644 index 8937ef3..0000000 --- a/boost/mpl/equal.hpp +++ /dev/null @@ -1,112 +0,0 @@ - -#ifndef BOOST_MPL_EQUAL_HPP_INCLUDED -#define BOOST_MPL_EQUAL_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -namespace aux { - -template< - typename Predicate - , typename LastIterator1 - , typename LastIterator2 - > -struct equal_pred -{ - template< - typename Iterator2 - , typename Iterator1 - > - struct apply - { - typedef typename and_< - not_< is_same > - , not_< is_same > - , aux::iter_apply2 - >::type type; - }; -}; - -template< - typename Sequence1 - , typename Sequence2 - , typename Predicate - > -struct equal_impl -{ - typedef typename begin::type first1_; - typedef typename begin::type first2_; - typedef typename end::type last1_; - typedef typename end::type last2_; - - typedef aux::iter_fold_if_impl< - first1_ - , first2_ - , next<> - , protect< aux::equal_pred > - , void_ - , always - > fold_; - - typedef typename fold_::iterator iter1_; - typedef typename fold_::state iter2_; - typedef and_< - is_same - , is_same - > result_; - - typedef typename result_::type type; -}; - - -} // namespace aux - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence1) - , typename BOOST_MPL_AUX_NA_PARAM(Sequence2) - , typename Predicate = is_same<_,_> - > -struct equal - : aux::msvc_eti_base< - typename aux::equal_impl::type - >::type -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,equal,(Sequence1,Sequence2)) -}; - -BOOST_MPL_AUX_NA_SPEC(2, equal) - -}} - -#endif // BOOST_MPL_EQUAL_HPP_INCLUDED diff --git a/boost/mpl/find_if.hpp b/boost/mpl/find_if.hpp deleted file mode 100644 index 83a007e..0000000 --- a/boost/mpl/find_if.hpp +++ /dev/null @@ -1,50 +0,0 @@ - -#ifndef BOOST_MPL_FIND_IF_HPP_INCLUDED -#define BOOST_MPL_FIND_IF_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -BOOST_MPL_AUX_COMMON_NAME_WKND(find_if) - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(Predicate) - > -struct find_if -{ - typedef typename iter_fold_if< - Sequence - , void - , mpl::arg<1> // ignore - , protect< aux::find_if_pred > - >::type result_; - - typedef typename second::type type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,find_if,(Sequence,Predicate)) -}; - -BOOST_MPL_AUX_NA_SPEC(2,find_if) - -}} - -#endif // BOOST_MPL_FIND_IF_HPP_INCLUDED diff --git a/boost/mpl/fold.hpp b/boost/mpl/fold.hpp deleted file mode 100644 index 0bc67ef..0000000 --- a/boost/mpl/fold.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -#ifndef BOOST_MPL_FOLD_HPP_INCLUDED -#define BOOST_MPL_FOLD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// Copyright David Abrahams 2001-2002 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(State) - , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) - > -struct fold -{ - typedef typename aux::fold_impl< - ::boost::mpl::O1_size::value - , typename begin::type - , typename end::type - , State - , ForwardOp - >::state type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(3,fold,(Sequence,State,ForwardOp)) -}; - -BOOST_MPL_AUX_NA_SPEC(3, fold) - -}} - -#endif // BOOST_MPL_FOLD_HPP_INCLUDED diff --git a/boost/mpl/front.hpp b/boost/mpl/front.hpp deleted file mode 100644 index b222ff2..0000000 --- a/boost/mpl/front.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef BOOST_MPL_FRONT_HPP_INCLUDED -#define BOOST_MPL_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct front - : front_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,front,(Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, front) - -}} - -#endif // BOOST_MPL_FRONT_HPP_INCLUDED diff --git a/boost/mpl/front_fwd.hpp b/boost/mpl/front_fwd.hpp deleted file mode 100644 index f01282a..0000000 --- a/boost/mpl/front_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_FRONT_FWD_HPP_INCLUDED -#define BOOST_MPL_FRONT_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct front_impl; -template< typename Sequence > struct front; - -}} - -#endif // BOOST_MPL_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/front_inserter.hpp b/boost/mpl/front_inserter.hpp deleted file mode 100644 index 0a6b197..0000000 --- a/boost/mpl/front_inserter.hpp +++ /dev/null @@ -1,33 +0,0 @@ - -#ifndef BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED -#define BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2003-2004 -// Copyright David Abrahams 2003-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template< - typename Sequence - > -struct front_inserter - : inserter< Sequence,push_front<> > -{ -}; - -}} - -#endif // BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/insert.hpp b/boost/mpl/insert.hpp deleted file mode 100644 index 5e379a4..0000000 --- a/boost/mpl/insert.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef BOOST_MPL_INSERT_HPP_INCLUDED -#define BOOST_MPL_INSERT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(Pos_or_T) - , typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct insert - : insert_impl< typename sequence_tag::type > - ::template apply< Sequence,Pos_or_T,T > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(3,insert,(Sequence,Pos_or_T,T)) -}; - -BOOST_MPL_AUX_NA_SPEC(3, insert) - -}} - -#endif // BOOST_MPL_INSERT_HPP_INCLUDED diff --git a/boost/mpl/insert_fwd.hpp b/boost/mpl/insert_fwd.hpp deleted file mode 100644 index ba6b161..0000000 --- a/boost/mpl/insert_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_INSERT_FWD_HPP_INCLUDED -#define BOOST_MPL_INSERT_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct insert_impl; -template< typename Sequence, typename Pos_or_T, typename T > struct insert; - -}} - -#endif // BOOST_MPL_INSERT_FWD_HPP_INCLUDED diff --git a/boost/mpl/insert_range.hpp b/boost/mpl/insert_range.hpp deleted file mode 100644 index 0c362f5..0000000 --- a/boost/mpl/insert_range.hpp +++ /dev/null @@ -1,41 +0,0 @@ - -#ifndef BOOST_MPL_INSERT_RANGE_HPP_INCLUDED -#define BOOST_MPL_INSERT_RANGE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(Pos) - , typename BOOST_MPL_AUX_NA_PARAM(Range) - > -struct insert_range - : insert_range_impl< typename sequence_tag::type > - ::template apply< Sequence,Pos,Range > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(3,insert_range,(Sequence,Pos,Range)) -}; - -BOOST_MPL_AUX_NA_SPEC(3, insert_range) - -}} - -#endif // BOOST_MPL_INSERT_RANGE_HPP_INCLUDED diff --git a/boost/mpl/insert_range_fwd.hpp b/boost/mpl/insert_range_fwd.hpp deleted file mode 100644 index d9c946f..0000000 --- a/boost/mpl/insert_range_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_INSERT_RANGE_FWD_HPP_INCLUDED -#define BOOST_MPL_INSERT_RANGE_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct insert_range_impl; -template< typename Sequence, typename Pos, typename Range > struct insert_range; - -}} - -#endif // BOOST_MPL_INSERT_RANGE_FWD_HPP_INCLUDED diff --git a/boost/mpl/inserter.hpp b/boost/mpl/inserter.hpp deleted file mode 100644 index 964df7f..0000000 --- a/boost/mpl/inserter.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -#ifndef BOOST_MPL_INSERTER_HPP_INCLUDED -#define BOOST_MPL_INSERTER_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2003-2004 -// Copyright David Abrahams 2003-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< - typename Sequence - , typename Operation - > -struct inserter -{ - typedef Sequence state; - typedef Operation operation; -}; - -}} - -#endif // BOOST_MPL_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/is_sequence.hpp b/boost/mpl/is_sequence.hpp deleted file mode 100644 index 68e036f..0000000 --- a/boost/mpl/is_sequence.hpp +++ /dev/null @@ -1,112 +0,0 @@ - -#ifndef BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED -#define BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2002-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) -# include -#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) -# include -#endif - -#include - -namespace boost { namespace mpl { - -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - -namespace aux { - -// agurt, 11/jun/03: -// MSVC 6.5/7.0 fails if 'has_begin' is instantiated on a class type that has a -// 'begin' member that doesn't name a type; e.g. 'has_begin< std::vector >' -// would fail; requiring 'T' to have _both_ 'tag' and 'begin' members workarounds -// the issue for most real-world cases -template< typename T > struct is_sequence_impl - : and_< - identity< aux::has_tag > - , identity< aux::has_begin > - > -{ -}; - -} // namespace aux - -template< - typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct is_sequence - : if_< -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) - aux::msvc_is_class -#else - boost::is_class -#endif - , aux::is_sequence_impl - , bool_ - >::type -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) -}; - -#elif defined(BOOST_MPL_CFG_NO_HAS_XXX) - -template< - typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct is_sequence - : bool_ -{ -}; - -#else - -template< - typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct is_sequence - : not_< is_same< typename begin::type, void_ > > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) -}; - -#endif // BOOST_MSVC - -#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) -template<> struct is_sequence - : bool_ -{ -}; -#endif - -BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, is_sequence) - -}} - -#endif // BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED diff --git a/boost/mpl/iter_fold.hpp b/boost/mpl/iter_fold.hpp deleted file mode 100644 index 1b56b79..0000000 --- a/boost/mpl/iter_fold.hpp +++ /dev/null @@ -1,49 +0,0 @@ - -#ifndef BOOST_MPL_ITER_FOLD_HPP_INCLUDED -#define BOOST_MPL_ITER_FOLD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// Copyright David Abrahams 2001-2002 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(State) - , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) - > -struct iter_fold -{ - typedef typename aux::iter_fold_impl< - ::boost::mpl::O1_size::value - , typename begin::type - , typename end::type - , State - , typename lambda::type - >::state type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(3,iter_fold,(Sequence,State,ForwardOp)) -}; - -BOOST_MPL_AUX_NA_SPEC(3, iter_fold) - -}} - -#endif // BOOST_MPL_ITER_FOLD_HPP_INCLUDED diff --git a/boost/mpl/iter_fold_if.hpp b/boost/mpl/iter_fold_if.hpp deleted file mode 100644 index 0115b7b..0000000 --- a/boost/mpl/iter_fold_if.hpp +++ /dev/null @@ -1,117 +0,0 @@ - -#ifndef BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED -#define BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2003-2004 -// Copyright Eric Friedman 2003 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -namespace aux { - -template< typename Predicate, typename LastIterator > -struct iter_fold_if_pred -{ - template< typename State, typename Iterator > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : and_< - not_< is_same > - , apply1 - > - { -#else - { - typedef and_< - not_< is_same > - , apply1 - > type; -#endif - }; -}; - -} // namespace aux - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(State) - , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) - , typename BOOST_MPL_AUX_NA_PARAM(ForwardPredicate) - , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp) - , typename BOOST_MPL_AUX_NA_PARAM(BackwardPredicate) - > -struct iter_fold_if -{ - - typedef typename begin::type first_; - typedef typename end::type last_; - - typedef typename eval_if< - is_na - , if_< is_na, always, always > - , identity - >::type backward_pred_; - -// cwpro8 doesn't like 'cut-off' type here (use typedef instead) -#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) && !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) - struct result_ : -#else - typedef -#endif - aux::iter_fold_if_impl< - first_ - , State - , ForwardOp - , protect< aux::iter_fold_if_pred< ForwardPredicate,last_ > > - , BackwardOp - , backward_pred_ - > -#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) && !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) - { }; -#else - result_; -#endif - -public: - - typedef pair< - typename result_::state - , typename result_::iterator - > type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT( - 6 - , iter_fold_if - , (Sequence,State,ForwardOp,ForwardPredicate,BackwardOp,BackwardPredicate) - ) -}; - -BOOST_MPL_AUX_NA_SPEC(6, iter_fold_if) - -}} - -#endif // BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED diff --git a/boost/mpl/iterator_category.hpp b/boost/mpl/iterator_category.hpp deleted file mode 100644 index d5ea4af..0000000 --- a/boost/mpl/iterator_category.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED -#define BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Iterator) - > -struct iterator_category -{ - typedef typename Iterator::category type; - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,iterator_category,(Iterator)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, iterator_category) - -}} - -#endif // BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED diff --git a/boost/mpl/iterator_range.hpp b/boost/mpl/iterator_range.hpp deleted file mode 100644 index a637e22..0000000 --- a/boost/mpl/iterator_range.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED -#define BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -struct iterator_range_tag; - -template< - typename BOOST_MPL_AUX_NA_PARAM(First) - , typename BOOST_MPL_AUX_NA_PARAM(Last) - > -struct iterator_range -{ - typedef iterator_range_tag tag; - typedef iterator_range type; - typedef First begin; - typedef Last end; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,iterator_range,(First,Last)) -}; - -BOOST_MPL_AUX_NA_SPEC(2, iterator_range) - -}} - -#endif // BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED diff --git a/boost/mpl/iterator_tags.hpp b/boost/mpl/iterator_tags.hpp deleted file mode 100644 index 7c3116a..0000000 --- a/boost/mpl/iterator_tags.hpp +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED -#define BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -namespace boost { namespace mpl { - -struct forward_iterator_tag : int_<0> { typedef forward_iterator_tag type; }; -struct bidirectional_iterator_tag : int_<1> { typedef bidirectional_iterator_tag type; }; -struct random_access_iterator_tag : int_<2> { typedef random_access_iterator_tag type; }; - -}} - -#endif // BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED diff --git a/boost/mpl/joint_view.hpp b/boost/mpl/joint_view.hpp deleted file mode 100644 index cd9cdda..0000000 --- a/boost/mpl/joint_view.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -#ifndef BOOST_MPL_JOINT_VIEW_HPP_INCLUDED -#define BOOST_MPL_JOINT_VIEW_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -namespace aux { -struct joint_view_tag; -} - -template<> -struct size_impl< aux::joint_view_tag > -{ - template < typename JointView > struct apply - : plus< - size - , size - > - {}; -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence1_) - , typename BOOST_MPL_AUX_NA_PARAM(Sequence2_) - > -struct joint_view -{ - typedef typename mpl::begin::type first1_; - typedef typename mpl::end::type last1_; - typedef typename mpl::begin::type first2_; - typedef typename mpl::end::type last2_; - - // agurt, 25/may/03: for the 'size_traits' implementation above - typedef Sequence1_ sequence1_; - typedef Sequence2_ sequence2_; - - typedef joint_view type; - typedef aux::joint_view_tag tag; - typedef joint_iter begin; - typedef joint_iter end; -}; - -BOOST_MPL_AUX_NA_SPEC(2, joint_view) - -}} - -#endif // BOOST_MPL_JOINT_VIEW_HPP_INCLUDED diff --git a/boost/mpl/limits/list.hpp b/boost/mpl/limits/list.hpp deleted file mode 100644 index b22d6a7..0000000 --- a/boost/mpl/limits/list.hpp +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef BOOST_MPL_LIMITS_LIST_HPP_INCLUDED -#define BOOST_MPL_LIMITS_LIST_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_LIMIT_LIST_SIZE) -# define BOOST_MPL_LIMIT_LIST_SIZE 20 -#endif - -#endif // BOOST_MPL_LIMITS_LIST_HPP_INCLUDED diff --git a/boost/mpl/limits/unrolling.hpp b/boost/mpl/limits/unrolling.hpp deleted file mode 100644 index 6dba942..0000000 --- a/boost/mpl/limits/unrolling.hpp +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED -#define BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_LIMIT_UNROLLING) -# define BOOST_MPL_LIMIT_UNROLLING 4 -#endif - -#endif // BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED diff --git a/boost/mpl/list.hpp b/boost/mpl/list.hpp deleted file mode 100644 index cff8a4d..0000000 --- a/boost/mpl/list.hpp +++ /dev/null @@ -1,57 +0,0 @@ - -#ifndef BOOST_MPL_LIST_HPP_INCLUDED -#define BOOST_MPL_LIST_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -# include -# include - -# include -# include -# include - -#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING) -# define AUX778076_LIST_HEADER \ - BOOST_PP_CAT(list,BOOST_MPL_LIMIT_LIST_SIZE).hpp \ - /**/ -#else -# define AUX778076_LIST_HEADER \ - BOOST_PP_CAT(list,BOOST_MPL_LIMIT_LIST_SIZE)##.hpp \ - /**/ -#endif - -# include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_HEADER) -# undef AUX778076_LIST_HEADER -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list.hpp -# include - -#else - -# include - -# define AUX778076_SEQUENCE_NAME list -# define AUX778076_SEQUENCE_LIMIT BOOST_MPL_LIMIT_LIST_SIZE -# include - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#endif // BOOST_MPL_LIST_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/O1_size.hpp b/boost/mpl/list/aux_/O1_size.hpp deleted file mode 100644 index ccbc3f1..0000000 --- a/boost/mpl/list/aux_/O1_size.hpp +++ /dev/null @@ -1,33 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template<> -struct O1_size_impl< aux::list_tag > -{ - template< typename List > struct apply - : List::size - { - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/begin_end.hpp b/boost/mpl/list/aux_/begin_end.hpp deleted file mode 100644 index b568bee..0000000 --- a/boost/mpl/list/aux_/begin_end.hpp +++ /dev/null @@ -1,44 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template<> -struct begin_impl< aux::list_tag > -{ - template< typename List > struct apply - { - typedef l_iter type; - }; -}; - -template<> -struct end_impl< aux::list_tag > -{ - template< typename > struct apply - { - typedef l_iter type; - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/clear.hpp b/boost/mpl/list/aux_/clear.hpp deleted file mode 100644 index b16162f..0000000 --- a/boost/mpl/list/aux_/clear.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template<> -struct clear_impl< aux::list_tag > -{ - template< typename List > struct apply - { - typedef l_end type; - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/empty.hpp b/boost/mpl/list/aux_/empty.hpp deleted file mode 100644 index 95f9243..0000000 --- a/boost/mpl/list/aux_/empty.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template<> -struct empty_impl< aux::list_tag > -{ - template< typename List > struct apply - : not_ - { - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/front.hpp b/boost/mpl/list/aux_/front.hpp deleted file mode 100644 index 9bea1fd..0000000 --- a/boost/mpl/list/aux_/front.hpp +++ /dev/null @@ -1,33 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template<> -struct front_impl< aux::list_tag > -{ - template< typename List > struct apply - { - typedef typename List::item type; - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/include_preprocessed.hpp b/boost/mpl/list/aux_/include_preprocessed.hpp deleted file mode 100644 index 4f7cab2..0000000 --- a/boost/mpl/list/aux_/include_preprocessed.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2001-2006 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION! - -#include - -#include -#include - -# define AUX778076_HEADER \ - aux_/preprocessed/plain/BOOST_MPL_PREPROCESSED_HEADER \ -/**/ - -#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(700)) -# define AUX778076_INCLUDE_STRING BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER) -# include AUX778076_INCLUDE_STRING -# undef AUX778076_INCLUDE_STRING -#else -# include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER) -#endif - -# undef AUX778076_HEADER - -#undef BOOST_MPL_PREPROCESSED_HEADER diff --git a/boost/mpl/list/aux_/item.hpp b/boost/mpl/list/aux_/item.hpp deleted file mode 100644 index 8505deb..0000000 --- a/boost/mpl/list/aux_/item.hpp +++ /dev/null @@ -1,55 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename Size - , typename T - , typename Next - > -struct l_item -{ -// agurt, 17/jul/03: to facilitate the deficient 'is_sequence' implementation -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - typedef int begin; -#endif - typedef aux::list_tag tag; - typedef l_item type; - - typedef Size size; - typedef T item; - typedef Next next; -}; - -struct l_end -{ -#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) - typedef int begin; -#endif - typedef aux::list_tag tag; - typedef l_end type; - typedef long_<0> size; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/iterator.hpp b/boost/mpl/list/aux_/iterator.hpp deleted file mode 100644 index 6b5ea78..0000000 --- a/boost/mpl/list/aux_/iterator.hpp +++ /dev/null @@ -1,76 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -template< typename Node > -struct l_iter -{ - typedef aux::l_iter_tag tag; - typedef forward_iterator_tag category; -}; - -template< typename Node > -struct deref< l_iter > -{ - typedef typename Node::item type; -}; - -template< typename Node > -struct next< l_iter > -{ - typedef l_iter< typename Node::next > type; -}; - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -template< typename Node > -struct l_iter -{ - typedef aux::l_iter_tag tag; - typedef forward_iterator_tag category; - typedef typename Node::item type; - typedef l_iter< typename mpl::next::type > next; -}; - -#endif - - -template<> struct l_iter -{ - typedef aux::l_iter_tag tag; - typedef forward_iterator_tag category; -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - typedef na type; - typedef l_iter next; -#endif -}; - -BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(1, l_iter) - -}} - -#endif // BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/numbered.hpp b/boost/mpl/list/aux_/numbered.hpp deleted file mode 100644 index 0cd49a6..0000000 --- a/boost/mpl/list/aux_/numbered.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION - -// Copyright Peter Dimov 2000-2002 -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if defined(BOOST_PP_IS_ITERATING) - -#include -#include -#include -#include - -#define i BOOST_PP_FRAME_ITERATION(1) - -#if i == 1 - -template< - BOOST_PP_ENUM_PARAMS(i, typename T) - > -struct list1 - : l_item< - long_<1> - , T0 - , l_end - > -{ - typedef list1 type; -}; - -#else - -# define MPL_AUX_LIST_TAIL(list, i, T) \ - BOOST_PP_CAT(list,BOOST_PP_DEC(i))< \ - BOOST_PP_ENUM_SHIFTED_PARAMS(i, T) \ - > \ - /**/ - -template< - BOOST_PP_ENUM_PARAMS(i, typename T) - > -struct BOOST_PP_CAT(list,i) - : l_item< - long_ - , T0 - , MPL_AUX_LIST_TAIL(list,i,T) - > -{ - typedef BOOST_PP_CAT(list,i) type; -}; - -# undef MPL_AUX_LIST_TAIL - -#endif // i == 1 - -#undef i - -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/list/aux_/numbered_c.hpp b/boost/mpl/list/aux_/numbered_c.hpp deleted file mode 100644 index 0006fd6..0000000 --- a/boost/mpl/list/aux_/numbered_c.hpp +++ /dev/null @@ -1,71 +0,0 @@ - -// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if defined(BOOST_PP_IS_ITERATING) - -#include -#include -#include -#include - -#define i BOOST_PP_FRAME_ITERATION(1) - -#if i == 1 - -template< - typename T - , BOOST_PP_ENUM_PARAMS(i, T C) - > -struct list1_c - : l_item< - long_<1> - , integral_c - , l_end - > -{ - typedef list1_c type; - typedef T value_type; -}; - -#else - -# define MPL_AUX_LIST_C_TAIL(list, i, C) \ - BOOST_PP_CAT(BOOST_PP_CAT(list,BOOST_PP_DEC(i)),_c) \ - /**/ - -template< - typename T - , BOOST_PP_ENUM_PARAMS(i, T C) - > -struct BOOST_PP_CAT(BOOST_PP_CAT(list,i),_c) - : l_item< - long_ - , integral_c - , MPL_AUX_LIST_C_TAIL(list,i,C) - > -{ - typedef BOOST_PP_CAT(BOOST_PP_CAT(list,i),_c) type; - typedef T value_type; -}; - -# undef MPL_AUX_LIST_C_TAIL - -#endif // i == 1 - -#undef i - -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/list/aux_/pop_front.hpp b/boost/mpl/list/aux_/pop_front.hpp deleted file mode 100644 index 46a0414..0000000 --- a/boost/mpl/list/aux_/pop_front.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template<> -struct pop_front_impl< aux::list_tag > -{ - template< typename List > struct apply - { - typedef typename mpl::next::type type; - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/preprocessed/plain/list10.hpp b/boost/mpl/list/aux_/preprocessed/plain/list10.hpp deleted file mode 100644 index 99368d2..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +++ /dev/null @@ -1,149 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list10.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T0 - > -struct list1 - : l_item< - long_<1> - , T0 - , l_end - > -{ - typedef list1 type; -}; - -template< - typename T0, typename T1 - > -struct list2 - : l_item< - long_<2> - , T0 - , list1 - > -{ - typedef list2 type; -}; - -template< - typename T0, typename T1, typename T2 - > -struct list3 - : l_item< - long_<3> - , T0 - , list2< T1,T2 > - > -{ - typedef list3 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3 - > -struct list4 - : l_item< - long_<4> - , T0 - , list3< T1,T2,T3 > - > -{ - typedef list4 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - > -struct list5 - : l_item< - long_<5> - , T0 - , list4< T1,T2,T3,T4 > - > -{ - typedef list5 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5 - > -struct list6 - : l_item< - long_<6> - , T0 - , list5< T1,T2,T3,T4,T5 > - > -{ - typedef list6 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6 - > -struct list7 - : l_item< - long_<7> - , T0 - , list6< T1,T2,T3,T4,T5,T6 > - > -{ - typedef list7 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7 - > -struct list8 - : l_item< - long_<8> - , T0 - , list7< T1,T2,T3,T4,T5,T6,T7 > - > -{ - typedef list8 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8 - > -struct list9 - : l_item< - long_<9> - , T0 - , list8< T1,T2,T3,T4,T5,T6,T7,T8 > - > -{ - typedef list9 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - > -struct list10 - : l_item< - long_<10> - , T0 - , list9< T1,T2,T3,T4,T5,T6,T7,T8,T9 > - > -{ - typedef list10 type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list10_c.hpp b/boost/mpl/list/aux_/preprocessed/plain/list10_c.hpp deleted file mode 100644 index 7133d71..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list10_c.hpp +++ /dev/null @@ -1,164 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list10_c.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T - , T C0 - > -struct list1_c - : l_item< - long_<1> - , integral_c< T,C0 > - , l_end - > -{ - typedef list1_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1 - > -struct list2_c - : l_item< - long_<2> - , integral_c< T,C0 > - , list1_c< T,C1 > - > -{ - typedef list2_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2 - > -struct list3_c - : l_item< - long_<3> - , integral_c< T,C0 > - , list2_c< T,C1,C2 > - > -{ - typedef list3_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3 - > -struct list4_c - : l_item< - long_<4> - , integral_c< T,C0 > - , list3_c< T,C1,C2,C3 > - > -{ - typedef list4_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4 - > -struct list5_c - : l_item< - long_<5> - , integral_c< T,C0 > - , list4_c< T,C1,C2,C3,C4 > - > -{ - typedef list5_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5 - > -struct list6_c - : l_item< - long_<6> - , integral_c< T,C0 > - , list5_c< T,C1,C2,C3,C4,C5 > - > -{ - typedef list6_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6 - > -struct list7_c - : l_item< - long_<7> - , integral_c< T,C0 > - , list6_c< T,C1,C2,C3,C4,C5,C6 > - > -{ - typedef list7_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7 - > -struct list8_c - : l_item< - long_<8> - , integral_c< T,C0 > - , list7_c< T,C1,C2,C3,C4,C5,C6,C7 > - > -{ - typedef list8_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8 - > -struct list9_c - : l_item< - long_<9> - , integral_c< T,C0 > - , list8_c< T,C1,C2,C3,C4,C5,C6,C7,C8 > - > -{ - typedef list9_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9 - > -struct list10_c - : l_item< - long_<10> - , integral_c< T,C0 > - , list9_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9 > - > -{ - typedef list10_c type; - typedef T value_type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list20.hpp b/boost/mpl/list/aux_/preprocessed/plain/list20.hpp deleted file mode 100644 index 750e495..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +++ /dev/null @@ -1,169 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list20.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10 - > -struct list11 - : l_item< - long_<11> - , T0 - , list10< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 > - > -{ - typedef list11 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11 - > -struct list12 - : l_item< - long_<12> - , T0 - , list11< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11 > - > -{ - typedef list12 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12 - > -struct list13 - : l_item< - long_<13> - , T0 - , list12< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 > - > -{ - typedef list13 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13 - > -struct list14 - : l_item< - long_<14> - , T0 - , list13< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 > - > -{ - typedef list14 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - > -struct list15 - : l_item< - long_<15> - , T0 - , list14< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14 > - > -{ - typedef list15 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15 - > -struct list16 - : l_item< - long_<16> - , T0 - , list15< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15 > - > -{ - typedef list16 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16 - > -struct list17 - : l_item< - long_<17> - , T0 - , list16< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16 > - > -{ - typedef list17 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17 - > -struct list18 - : l_item< - long_<18> - , T0 - , list17< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17 > - > -{ - typedef list18 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18 - > -struct list19 - : l_item< - long_<19> - , T0 - , list18< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18 > - > -{ - typedef list19 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - > -struct list20 - : l_item< - long_<20> - , T0 - , list19< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19 > - > -{ - typedef list20 type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list20_c.hpp b/boost/mpl/list/aux_/preprocessed/plain/list20_c.hpp deleted file mode 100644 index 7f15acf..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list20_c.hpp +++ /dev/null @@ -1,173 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list20_c.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - > -struct list11_c - : l_item< - long_<11> - , integral_c< T,C0 > - , list10_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10 > - > -{ - typedef list11_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11 - > -struct list12_c - : l_item< - long_<12> - , integral_c< T,C0 > - , list11_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11 > - > -{ - typedef list12_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12 - > -struct list13_c - : l_item< - long_<13> - , integral_c< T,C0 > - , list12_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12 > - > -{ - typedef list13_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13 - > -struct list14_c - : l_item< - long_<14> - , integral_c< T,C0 > - , list13_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13 > - > -{ - typedef list14_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14 - > -struct list15_c - : l_item< - long_<15> - , integral_c< T,C0 > - , list14_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14 > - > -{ - typedef list15_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15 - > -struct list16_c - : l_item< - long_<16> - , integral_c< T,C0 > - , list15_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15 > - > -{ - typedef list16_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16 - > -struct list17_c - : l_item< - long_<17> - , integral_c< T,C0 > - , list16_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16 > - > -{ - typedef list17_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17 - > -struct list18_c - : l_item< - long_<18> - , integral_c< T,C0 > - , list17_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17 > - > -{ - typedef list18_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18 - > -struct list19_c - : l_item< - long_<19> - , integral_c< T,C0 > - , list18_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18 > - > -{ - typedef list19_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19 - > -struct list20_c - : l_item< - long_<20> - , integral_c< T,C0 > - , list19_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19 > - > -{ - typedef list20_c type; - typedef T value_type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list30.hpp b/boost/mpl/list/aux_/preprocessed/plain/list30.hpp deleted file mode 100644 index 5459101..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list30.hpp +++ /dev/null @@ -1,189 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list30.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20 - > -struct list21 - : l_item< - long_<21> - , T0 - , list20< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20 > - > -{ - typedef list21 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21 - > -struct list22 - : l_item< - long_<22> - , T0 - , list21< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21 > - > -{ - typedef list22 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22 - > -struct list23 - : l_item< - long_<23> - , T0 - , list22< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22 > - > -{ - typedef list23 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23 - > -struct list24 - : l_item< - long_<24> - , T0 - , list23< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23 > - > -{ - typedef list24 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - > -struct list25 - : l_item< - long_<25> - , T0 - , list24< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24 > - > -{ - typedef list25 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25 - > -struct list26 - : l_item< - long_<26> - , T0 - , list25< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25 > - > -{ - typedef list26 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26 - > -struct list27 - : l_item< - long_<27> - , T0 - , list26< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26 > - > -{ - typedef list27 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27 - > -struct list28 - : l_item< - long_<28> - , T0 - , list27< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27 > - > -{ - typedef list28 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28 - > -struct list29 - : l_item< - long_<29> - , T0 - , list28< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28 > - > -{ - typedef list29 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - > -struct list30 - : l_item< - long_<30> - , T0 - , list29< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29 > - > -{ - typedef list30 type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list30_c.hpp b/boost/mpl/list/aux_/preprocessed/plain/list30_c.hpp deleted file mode 100644 index 5393d79..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list30_c.hpp +++ /dev/null @@ -1,183 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list30_c.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - > -struct list21_c - : l_item< - long_<21> - , integral_c< T,C0 > - , list20_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20 > - > -{ - typedef list21_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21 - > -struct list22_c - : l_item< - long_<22> - , integral_c< T,C0 > - , list21_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21 > - > -{ - typedef list22_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22 - > -struct list23_c - : l_item< - long_<23> - , integral_c< T,C0 > - , list22_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22 > - > -{ - typedef list23_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23 - > -struct list24_c - : l_item< - long_<24> - , integral_c< T,C0 > - , list23_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23 > - > -{ - typedef list24_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24 - > -struct list25_c - : l_item< - long_<25> - , integral_c< T,C0 > - , list24_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24 > - > -{ - typedef list25_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25 - > -struct list26_c - : l_item< - long_<26> - , integral_c< T,C0 > - , list25_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25 > - > -{ - typedef list26_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26 - > -struct list27_c - : l_item< - long_<27> - , integral_c< T,C0 > - , list26_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26 > - > -{ - typedef list27_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27 - > -struct list28_c - : l_item< - long_<28> - , integral_c< T,C0 > - , list27_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27 > - > -{ - typedef list28_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28 - > -struct list29_c - : l_item< - long_<29> - , integral_c< T,C0 > - , list28_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28 > - > -{ - typedef list29_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29 - > -struct list30_c - : l_item< - long_<30> - , integral_c< T,C0 > - , list29_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29 > - > -{ - typedef list30_c type; - typedef T value_type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list40.hpp b/boost/mpl/list/aux_/preprocessed/plain/list40.hpp deleted file mode 100644 index 68c6761..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list40.hpp +++ /dev/null @@ -1,209 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list40.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30 - > -struct list31 - : l_item< - long_<31> - , T0 - , list30< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30 > - > -{ - typedef list31 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31 - > -struct list32 - : l_item< - long_<32> - , T0 - , list31< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31 > - > -{ - typedef list32 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32 - > -struct list33 - : l_item< - long_<33> - , T0 - , list32< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32 > - > -{ - typedef list33 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33 - > -struct list34 - : l_item< - long_<34> - , T0 - , list33< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33 > - > -{ - typedef list34 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - > -struct list35 - : l_item< - long_<35> - , T0 - , list34< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34 > - > -{ - typedef list35 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35 - > -struct list36 - : l_item< - long_<36> - , T0 - , list35< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35 > - > -{ - typedef list36 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36 - > -struct list37 - : l_item< - long_<37> - , T0 - , list36< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36 > - > -{ - typedef list37 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37 - > -struct list38 - : l_item< - long_<38> - , T0 - , list37< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37 > - > -{ - typedef list38 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38 - > -struct list39 - : l_item< - long_<39> - , T0 - , list38< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38 > - > -{ - typedef list39 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - > -struct list40 - : l_item< - long_<40> - , T0 - , list39< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39 > - > -{ - typedef list40 type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list40_c.hpp b/boost/mpl/list/aux_/preprocessed/plain/list40_c.hpp deleted file mode 100644 index 0c51ba2..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list40_c.hpp +++ /dev/null @@ -1,193 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list40_c.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - > -struct list31_c - : l_item< - long_<31> - , integral_c< T,C0 > - , list30_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30 > - > -{ - typedef list31_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31 - > -struct list32_c - : l_item< - long_<32> - , integral_c< T,C0 > - , list31_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31 > - > -{ - typedef list32_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32 - > -struct list33_c - : l_item< - long_<33> - , integral_c< T,C0 > - , list32_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32 > - > -{ - typedef list33_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33 - > -struct list34_c - : l_item< - long_<34> - , integral_c< T,C0 > - , list33_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33 > - > -{ - typedef list34_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34 - > -struct list35_c - : l_item< - long_<35> - , integral_c< T,C0 > - , list34_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34 > - > -{ - typedef list35_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35 - > -struct list36_c - : l_item< - long_<36> - , integral_c< T,C0 > - , list35_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35 > - > -{ - typedef list36_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36 - > -struct list37_c - : l_item< - long_<37> - , integral_c< T,C0 > - , list36_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36 > - > -{ - typedef list37_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37 - > -struct list38_c - : l_item< - long_<38> - , integral_c< T,C0 > - , list37_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37 > - > -{ - typedef list38_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38 - > -struct list39_c - : l_item< - long_<39> - , integral_c< T,C0 > - , list38_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38 > - > -{ - typedef list39_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39 - > -struct list40_c - : l_item< - long_<40> - , integral_c< T,C0 > - , list39_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39 > - > -{ - typedef list40_c type; - typedef T value_type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list50.hpp b/boost/mpl/list/aux_/preprocessed/plain/list50.hpp deleted file mode 100644 index 4cc22da..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list50.hpp +++ /dev/null @@ -1,229 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list50.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40 - > -struct list41 - : l_item< - long_<41> - , T0 - , list40< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40 > - > -{ - typedef list41 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41 - > -struct list42 - : l_item< - long_<42> - , T0 - , list41< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41 > - > -{ - typedef list42 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42 - > -struct list43 - : l_item< - long_<43> - , T0 - , list42< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42 > - > -{ - typedef list43 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43 - > -struct list44 - : l_item< - long_<44> - , T0 - , list43< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43 > - > -{ - typedef list44 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - > -struct list45 - : l_item< - long_<45> - , T0 - , list44< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44 > - > -{ - typedef list45 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - , typename T45 - > -struct list46 - : l_item< - long_<46> - , T0 - , list45< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45 > - > -{ - typedef list46 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - , typename T45, typename T46 - > -struct list47 - : l_item< - long_<47> - , T0 - , list46< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46 > - > -{ - typedef list47 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - , typename T45, typename T46, typename T47 - > -struct list48 - : l_item< - long_<48> - , T0 - , list47< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47 > - > -{ - typedef list48 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - , typename T45, typename T46, typename T47, typename T48 - > -struct list49 - : l_item< - long_<49> - , T0 - , list48< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48 > - > -{ - typedef list49 type; -}; - -template< - typename T0, typename T1, typename T2, typename T3, typename T4 - , typename T5, typename T6, typename T7, typename T8, typename T9 - , typename T10, typename T11, typename T12, typename T13, typename T14 - , typename T15, typename T16, typename T17, typename T18, typename T19 - , typename T20, typename T21, typename T22, typename T23, typename T24 - , typename T25, typename T26, typename T27, typename T28, typename T29 - , typename T30, typename T31, typename T32, typename T33, typename T34 - , typename T35, typename T36, typename T37, typename T38, typename T39 - , typename T40, typename T41, typename T42, typename T43, typename T44 - , typename T45, typename T46, typename T47, typename T48, typename T49 - > -struct list50 - : l_item< - long_<50> - , T0 - , list49< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48,T49 > - > -{ - typedef list50 type; -}; - -}} diff --git a/boost/mpl/list/aux_/preprocessed/plain/list50_c.hpp b/boost/mpl/list/aux_/preprocessed/plain/list50_c.hpp deleted file mode 100644 index 28c061d..0000000 --- a/boost/mpl/list/aux_/preprocessed/plain/list50_c.hpp +++ /dev/null @@ -1,203 +0,0 @@ - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -// Preprocessed version of "boost/mpl/list/list50_c.hpp" header -// -- DO NOT modify by hand! - -namespace boost { namespace mpl { - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - > -struct list41_c - : l_item< - long_<41> - , integral_c< T,C0 > - , list40_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40 > - > -{ - typedef list41_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41 - > -struct list42_c - : l_item< - long_<42> - , integral_c< T,C0 > - , list41_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41 > - > -{ - typedef list42_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42 - > -struct list43_c - : l_item< - long_<43> - , integral_c< T,C0 > - , list42_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42 > - > -{ - typedef list43_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43 - > -struct list44_c - : l_item< - long_<44> - , integral_c< T,C0 > - , list43_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43 > - > -{ - typedef list44_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44 - > -struct list45_c - : l_item< - long_<45> - , integral_c< T,C0 > - , list44_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44 > - > -{ - typedef list45_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44, T C45 - > -struct list46_c - : l_item< - long_<46> - , integral_c< T,C0 > - , list45_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45 > - > -{ - typedef list46_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44, T C45, T C46 - > -struct list47_c - : l_item< - long_<47> - , integral_c< T,C0 > - , list46_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46 > - > -{ - typedef list47_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44, T C45, T C46, T C47 - > -struct list48_c - : l_item< - long_<48> - , integral_c< T,C0 > - , list47_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47 > - > -{ - typedef list48_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48 - > -struct list49_c - : l_item< - long_<49> - , integral_c< T,C0 > - , list48_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47,C48 > - > -{ - typedef list49_c type; - typedef T value_type; -}; - -template< - typename T - , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 - , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 - , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 - , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 - , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48, T C49 - > -struct list50_c - : l_item< - long_<50> - , integral_c< T,C0 > - , list49_c< T,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47,C48,C49 > - > -{ - typedef list50_c type; - typedef T value_type; -}; - -}} diff --git a/boost/mpl/list/aux_/push_back.hpp b/boost/mpl/list/aux_/push_back.hpp deleted file mode 100644 index 8f3b73e..0000000 --- a/boost/mpl/list/aux_/push_back.hpp +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template< typename Tag > struct has_push_back_impl; - -template<> -struct has_push_back_impl< aux::list_tag > -{ - template< typename Seq > struct apply - : false_ - { - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/push_front.hpp b/boost/mpl/list/aux_/push_front.hpp deleted file mode 100644 index fcfbe4a..0000000 --- a/boost/mpl/list/aux_/push_front.hpp +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template<> -struct push_front_impl< aux::list_tag > -{ - template< typename List, typename T > struct apply - { - typedef l_item< - typename next::type - , T - , typename List::type - > type; - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/size.hpp b/boost/mpl/list/aux_/size.hpp deleted file mode 100644 index f5e7fea..0000000 --- a/boost/mpl/list/aux_/size.hpp +++ /dev/null @@ -1,33 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template<> -struct size_impl< aux::list_tag > -{ - template< typename List > struct apply - : List::size - { - }; -}; - -}} - -#endif // BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED diff --git a/boost/mpl/list/aux_/tag.hpp b/boost/mpl/list/aux_/tag.hpp deleted file mode 100644 index f5ed2bb..0000000 --- a/boost/mpl/list/aux_/tag.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED -#define BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { namespace aux { - -struct list_tag; -struct l_iter_tag; - -}}} - -#endif // BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED diff --git a/boost/mpl/list/list0.hpp b/boost/mpl/list/list0.hpp deleted file mode 100644 index 8e06b8d..0000000 --- a/boost/mpl/list/list0.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST0_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST0_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< typename Dummy = na > struct list0; - -template<> struct list0 - : l_end -{ - typedef l_end type; -}; - -}} - -#endif // BOOST_MPL_LIST_LIST0_HPP_INCLUDED diff --git a/boost/mpl/list/list0_c.hpp b/boost/mpl/list/list0_c.hpp deleted file mode 100644 index 807ca1c..0000000 --- a/boost/mpl/list/list0_c.hpp +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST0_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST0_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -namespace boost { namespace mpl { - -template< typename T > struct list0_c - : l_end -{ - typedef l_end type; - typedef T value_type; -}; - -}} - -#endif // BOOST_MPL_LIST_LIST0_C_HPP_INCLUDED diff --git a/boost/mpl/list/list10.hpp b/boost/mpl/list/list10.hpp deleted file mode 100644 index d32d0d8..0000000 --- a/boost/mpl/list/list10.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST10_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST10_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list10.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(1, 10, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST10_HPP_INCLUDED diff --git a/boost/mpl/list/list10_c.hpp b/boost/mpl/list/list10_c.hpp deleted file mode 100644 index 25c8f9d..0000000 --- a/boost/mpl/list/list10_c.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST10_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST10_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list10_c.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(1, 10, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST10_C_HPP_INCLUDED diff --git a/boost/mpl/list/list20.hpp b/boost/mpl/list/list20.hpp deleted file mode 100644 index 724cabd..0000000 --- a/boost/mpl/list/list20.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST20_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST20_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list20.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(11, 20, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST20_HPP_INCLUDED diff --git a/boost/mpl/list/list20_c.hpp b/boost/mpl/list/list20_c.hpp deleted file mode 100644 index 0026f69..0000000 --- a/boost/mpl/list/list20_c.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST20_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST20_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list20_c.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(11, 20, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST20_C_HPP_INCLUDED diff --git a/boost/mpl/list/list30.hpp b/boost/mpl/list/list30.hpp deleted file mode 100644 index a9004c7..0000000 --- a/boost/mpl/list/list30.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST30_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST30_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list30.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(21, 30, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST30_HPP_INCLUDED diff --git a/boost/mpl/list/list30_c.hpp b/boost/mpl/list/list30_c.hpp deleted file mode 100644 index c996574..0000000 --- a/boost/mpl/list/list30_c.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST30_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST30_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list30_c.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(21, 30, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST30_C_HPP_INCLUDED diff --git a/boost/mpl/list/list40.hpp b/boost/mpl/list/list40.hpp deleted file mode 100644 index 02f869e..0000000 --- a/boost/mpl/list/list40.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST40_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST40_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list40.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(31, 40, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST40_HPP_INCLUDED diff --git a/boost/mpl/list/list40_c.hpp b/boost/mpl/list/list40_c.hpp deleted file mode 100644 index 808d599..0000000 --- a/boost/mpl/list/list40_c.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST40_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST40_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list40_c.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(31, 40, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST40_C_HPP_INCLUDED diff --git a/boost/mpl/list/list50.hpp b/boost/mpl/list/list50.hpp deleted file mode 100644 index f16c68c..0000000 --- a/boost/mpl/list/list50.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST50_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST50_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list50.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(41, 50, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST50_HPP_INCLUDED diff --git a/boost/mpl/list/list50_c.hpp b/boost/mpl/list/list50_c.hpp deleted file mode 100644 index 20692d8..0000000 --- a/boost/mpl/list/list50_c.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef BOOST_MPL_LIST_LIST50_C_HPP_INCLUDED -#define BOOST_MPL_LIST_LIST50_C_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#if !defined(BOOST_MPL_PREPROCESSING_MODE) -# include -#endif - -#include - -#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ - && !defined(BOOST_MPL_PREPROCESSING_MODE) - -# define BOOST_MPL_PREPROCESSED_HEADER list50_c.hpp -# include - -#else - -# include - -namespace boost { namespace mpl { - -# define BOOST_PP_ITERATION_PARAMS_1 \ - (3,(41, 50, )) -# include BOOST_PP_ITERATE() - -}} - -#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS - -#endif // BOOST_MPL_LIST_LIST50_C_HPP_INCLUDED diff --git a/boost/mpl/long.hpp b/boost/mpl/long.hpp deleted file mode 100644 index c455267..0000000 --- a/boost/mpl/long.hpp +++ /dev/null @@ -1,22 +0,0 @@ - -#ifndef BOOST_MPL_LONG_HPP_INCLUDED -#define BOOST_MPL_LONG_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -#define AUX_WRAPPER_VALUE_TYPE long -#include - -#endif // BOOST_MPL_LONG_HPP_INCLUDED diff --git a/boost/mpl/long_fwd.hpp b/boost/mpl/long_fwd.hpp deleted file mode 100644 index 5f62f2b..0000000 --- a/boost/mpl/long_fwd.hpp +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef BOOST_MPL_LONG_FWD_HPP_INCLUDED -#define BOOST_MPL_LONG_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include - -BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN - -template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct long_; - -BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE -BOOST_MPL_AUX_ADL_BARRIER_DECL(long_) - -#endif // BOOST_MPL_LONG_FWD_HPP_INCLUDED diff --git a/boost/mpl/max_element.hpp b/boost/mpl/max_element.hpp deleted file mode 100644 index 33244f3..0000000 --- a/boost/mpl/max_element.hpp +++ /dev/null @@ -1,72 +0,0 @@ - -#ifndef BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED -#define BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -BOOST_MPL_AUX_COMMON_NAME_WKND(max_element) - -namespace aux { - -template< typename Predicate > -struct select_max -{ - template< typename OldIterator, typename Iterator > - struct apply - { - typedef typename apply2< - Predicate - , typename deref::type - , typename deref::type - >::type condition_; - - typedef typename if_< - condition_ - , Iterator - , OldIterator - >::type type; - }; -}; - -} // namespace aux - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename Predicate = less<_,_> - > -struct max_element - : iter_fold< - Sequence - , typename begin::type - , protect< aux::select_max > - > -{ -}; - -BOOST_MPL_AUX_NA_SPEC(1, max_element) - -}} - -#endif // BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED diff --git a/boost/mpl/min_max.hpp b/boost/mpl/min_max.hpp deleted file mode 100644 index 77545cd..0000000 --- a/boost/mpl/min_max.hpp +++ /dev/null @@ -1,46 +0,0 @@ - -#ifndef BOOST_MPL_MIN_MAX_HPP_INCLUDED -#define BOOST_MPL_MIN_MAX_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2008 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(N1) - , typename BOOST_MPL_AUX_NA_PARAM(N2) - > -struct min - : if_< less,N1,N2 > -{ -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(N1) - , typename BOOST_MPL_AUX_NA_PARAM(N2) - > -struct max - : if_< less,N2,N1 > -{ -}; - -BOOST_MPL_AUX_NA_SPEC(2, min) -BOOST_MPL_AUX_NA_SPEC(2, max) - -}} - -#endif // BOOST_MPL_MIN_MAX_HPP_INCLUDED diff --git a/boost/mpl/negate.hpp b/boost/mpl/negate.hpp deleted file mode 100644 index d6aa065..0000000 --- a/boost/mpl/negate.hpp +++ /dev/null @@ -1,81 +0,0 @@ - -#ifndef BOOST_MPL_NEGATE_HPP_INCLUDED -#define BOOST_MPL_NEGATE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< typename Tag > struct negate_impl; - -template< typename T > struct negate_tag -{ - typedef typename T::tag type; -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(N) - > -struct negate -#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG) - : negate_impl< - typename negate_tag::type - >::template apply::type -#else - : aux::msvc_eti_base< typename apply_wrap1< - negate_impl< typename negate_tag::type > - , N - >::type >::type -#endif -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, negate, (N)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, negate) - - -#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC) -namespace aux { -template< typename T, T n > struct negate_wknd -{ - BOOST_STATIC_CONSTANT(T, value = -n); - typedef integral_c type; -}; -} -#endif - -template<> -struct negate_impl -{ -#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC) - template< typename N > struct apply - : aux::negate_wknd< typename N::value_type, N::value > -#else - template< typename N > struct apply - : integral_c< typename N::value_type, (-N::value) > -#endif - { - }; -}; - -}} - -#endif // BOOST_MPL_NEGATE_HPP_INCLUDED diff --git a/boost/mpl/pair.hpp b/boost/mpl/pair.hpp deleted file mode 100644 index 67c01d7..0000000 --- a/boost/mpl/pair.hpp +++ /dev/null @@ -1,70 +0,0 @@ - -#ifndef BOOST_MPL_PAIR_HPP_INCLUDED -#define BOOST_MPL_PAIR_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(T1) - , typename BOOST_MPL_AUX_NA_PARAM(T2) - > -struct pair -{ - typedef pair type; - typedef T1 first; - typedef T2 second; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,pair,(T1,T2)) -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(P) - > -struct first -{ -#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) - typedef typename P::first type; -#else - typedef typename aux::msvc_eti_base

::first type; -#endif - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,first,(P)) -}; - -template< - typename BOOST_MPL_AUX_NA_PARAM(P) - > -struct second -{ -#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) - typedef typename P::second type; -#else - typedef typename aux::msvc_eti_base

::second type; -#endif - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,second,(P)) -}; - - -BOOST_MPL_AUX_NA_SPEC_NO_ETI(2, pair) -BOOST_MPL_AUX_NA_SPEC(1, first) -BOOST_MPL_AUX_NA_SPEC(1, second) - -}} - -#endif // BOOST_MPL_PAIR_HPP_INCLUDED diff --git a/boost/mpl/pair_view.hpp b/boost/mpl/pair_view.hpp deleted file mode 100644 index a72cf92..0000000 --- a/boost/mpl/pair_view.hpp +++ /dev/null @@ -1,169 +0,0 @@ - -#ifndef BOOST_MPL_PAIR_VIEW_HPP_INCLUDED -#define BOOST_MPL_PAIR_VIEW_HPP_INCLUDED - -// Copyright David Abrahams 2003-2004 -// Copyright Aleksey Gurtovoy 2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -namespace aux { -struct pair_iter_tag; - -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -template< typename Iter1, typename Iter2, typename Category > -struct pair_iter; - -template< typename Category > struct prior_pair_iter -{ - template< typename Iter1, typename Iter2 > struct apply - { - typedef typename mpl::prior::type i1_; - typedef typename mpl::prior::type i2_; - typedef pair_iter type; - }; -}; - -template<> struct prior_pair_iter -{ - template< typename Iter1, typename Iter2 > struct apply - { - typedef pair_iter type; - }; -}; - -#endif -} - -template< - typename Iter1 - , typename Iter2 - , typename Category - > -struct pair_iter -{ - typedef aux::pair_iter_tag tag; - typedef Category category; - typedef Iter1 first; - typedef Iter2 second; - -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - typedef pair< - typename deref::type - , typename deref::type - > type; - - typedef typename mpl::next::type i1_; - typedef typename mpl::next::type i2_; - typedef pair_iter next; - - typedef apply_wrap2< aux::prior_pair_iter,Iter1,Iter2 >::type prior; -#endif -}; - - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -template< typename Iter1, typename Iter2, typename C > -struct deref< pair_iter > -{ - typedef pair< - typename deref::type - , typename deref::type - > type; -}; - -template< typename Iter1, typename Iter2, typename C > -struct next< pair_iter > -{ - typedef typename mpl::next::type i1_; - typedef typename mpl::next::type i2_; - typedef pair_iter type; -}; - -template< typename Iter1, typename Iter2, typename C > -struct prior< pair_iter > -{ - typedef typename mpl::prior::type i1_; - typedef typename mpl::prior::type i2_; - typedef pair_iter type; -}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - -template<> struct advance_impl -{ - template< typename Iter, typename D > struct apply - { - typedef typename mpl::advance< typename Iter::first,D >::type i1_; - typedef typename mpl::advance< typename Iter::second,D >::type i2_; - typedef pair_iter type; - }; -}; - -template<> struct distance_impl -{ - template< typename Iter1, typename Iter2 > struct apply - { - // agurt, 10/nov/04: MSVC 6.5 ICE-s on forwarding - typedef typename mpl::distance< - typename first::type - , typename first::type - >::type type; - }; -}; - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence1) - , typename BOOST_MPL_AUX_NA_PARAM(Sequence2) - > -struct pair_view -{ - typedef nested_begin_end_tag tag; - - typedef typename begin::type iter1_; - typedef typename begin::type iter2_; - typedef typename min< - typename iterator_category::type - , typename iterator_category::type - >::type category_; - - typedef pair_iter begin; - - typedef pair_iter< - typename end::type - , typename end::type - , category_ - > end; -}; - -BOOST_MPL_AUX_NA_SPEC(2, pair_view) - -}} - -#endif // BOOST_MPL_PAIR_VIEW_HPP_INCLUDED diff --git a/boost/mpl/plus.hpp b/boost/mpl/plus.hpp deleted file mode 100644 index 455920b..0000000 --- a/boost/mpl/plus.hpp +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef BOOST_MPL_PLUS_HPP_INCLUDED -#define BOOST_MPL_PLUS_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#define AUX778076_OP_NAME plus -#define AUX778076_OP_TOKEN + -#include - -#endif // BOOST_MPL_PLUS_HPP_INCLUDED diff --git a/boost/mpl/pop_front_fwd.hpp b/boost/mpl/pop_front_fwd.hpp deleted file mode 100644 index 719c8b2..0000000 --- a/boost/mpl/pop_front_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED -#define BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct pop_front_impl; -template< typename Sequence > struct pop_front; - -}} - -#endif // BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/prior.hpp b/boost/mpl/prior.hpp deleted file mode 100644 index 849802c..0000000 --- a/boost/mpl/prior.hpp +++ /dev/null @@ -1,19 +0,0 @@ - -#ifndef BOOST_MPL_PRIOR_HPP_INCLUDED -#define BOOST_MPL_PRIOR_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -#endif // BOOST_MPL_PRIOR_HPP_INCLUDED diff --git a/boost/mpl/push_back.hpp b/boost/mpl/push_back.hpp deleted file mode 100644 index 95a2587..0000000 --- a/boost/mpl/push_back.hpp +++ /dev/null @@ -1,53 +0,0 @@ - -#ifndef BOOST_MPL_PUSH_BACK_HPP_INCLUDED -#define BOOST_MPL_PUSH_BACK_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct push_back - : push_back_impl< typename sequence_tag::type > - ::template apply< Sequence,T > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_back,(Sequence,T)) -}; - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct has_push_back - : has_push_back_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_back,(Sequence)) -}; - - -BOOST_MPL_AUX_NA_SPEC(2, push_back) -BOOST_MPL_AUX_NA_SPEC(1, has_push_back) - -}} - -#endif // BOOST_MPL_PUSH_BACK_HPP_INCLUDED diff --git a/boost/mpl/push_back_fwd.hpp b/boost/mpl/push_back_fwd.hpp deleted file mode 100644 index 7a4f7a7..0000000 --- a/boost/mpl/push_back_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED -#define BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct push_back_impl; -template< typename Sequence, typename T > struct push_back; - -}} - -#endif // BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED diff --git a/boost/mpl/push_front.hpp b/boost/mpl/push_front.hpp deleted file mode 100644 index e4d0dfb..0000000 --- a/boost/mpl/push_front.hpp +++ /dev/null @@ -1,52 +0,0 @@ - -#ifndef BOOST_MPL_PUSH_FRONT_HPP_INCLUDED -#define BOOST_MPL_PUSH_FRONT_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct push_front - : push_front_impl< typename sequence_tag::type > - ::template apply< Sequence,T > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_front,(Sequence,T)) -}; - - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct has_push_front - : has_push_front_impl< typename sequence_tag::type > - ::template apply< Sequence > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_front,(Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(2, push_front) -BOOST_MPL_AUX_NA_SPEC(1, has_push_front) - -}} - -#endif // BOOST_MPL_PUSH_FRONT_HPP_INCLUDED diff --git a/boost/mpl/push_front_fwd.hpp b/boost/mpl/push_front_fwd.hpp deleted file mode 100644 index d6ad5af..0000000 --- a/boost/mpl/push_front_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED -#define BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct push_front_impl; -template< typename Sequence, typename T > struct push_front; - -}} - -#endif // BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/reverse_fold.hpp b/boost/mpl/reverse_fold.hpp deleted file mode 100644 index 87c26a9..0000000 --- a/boost/mpl/reverse_fold.hpp +++ /dev/null @@ -1,50 +0,0 @@ - -#ifndef BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED -#define BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2001-2004 -// Copyright David Abrahams 2001-2002 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - , typename BOOST_MPL_AUX_NA_PARAM(State) - , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp) - , typename ForwardOp = arg<1> - > -struct reverse_fold -{ - typedef typename aux::reverse_fold_impl< - ::boost::mpl::O1_size::value - , typename begin::type - , typename end::type - , State - , BackwardOp - , ForwardOp - >::state type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(3,reverse_fold,(Sequence,State,BackwardOp)) -}; - -BOOST_MPL_AUX_NA_SPEC(3, reverse_fold) - -}} - -#endif // BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED diff --git a/boost/mpl/same_as.hpp b/boost/mpl/same_as.hpp deleted file mode 100644 index 4be20bc..0000000 --- a/boost/mpl/same_as.hpp +++ /dev/null @@ -1,55 +0,0 @@ - -#ifndef BOOST_MPL_SAME_AS_HPP_INCLUDED -#define BOOST_MPL_SAME_AS_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -#include - -namespace boost { namespace mpl { - -template< typename T1 > -struct same_as -{ - template< typename T2 > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : is_same - { -#else - { - typedef typename is_same::type type; -#endif - }; -}; - -template< typename T1 > -struct not_same_as -{ - template< typename T2 > struct apply -#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) - : not_< is_same > - { -#else - { - typedef typename not_< is_same >::type type; -#endif - }; -}; - -}} - -#endif // BOOST_MPL_SAME_AS_HPP_INCLUDED diff --git a/boost/mpl/sequence_tag.hpp b/boost/mpl/sequence_tag.hpp deleted file mode 100644 index f87d92b..0000000 --- a/boost/mpl/sequence_tag.hpp +++ /dev/null @@ -1,124 +0,0 @@ - -#ifndef BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED -#define BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -// agurt, 27/nov/02: have to use a simplistic 'sequence_tag' implementation -// on MSVC to avoid dreadful "internal structure overflow" error -#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ - || defined(BOOST_MPL_CFG_NO_HAS_XXX) - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct sequence_tag -{ - typedef typename Sequence::tag type; -}; - -#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) - -// agurt, 07/feb/03: workaround for what seems to be MSVC 7.0-specific ETI issue - -namespace aux { - -template< bool > -struct sequence_tag_impl -{ - template< typename Sequence > struct result_ - { - typedef typename Sequence::tag type; - }; -}; - -template<> -struct sequence_tag_impl -{ - template< typename Sequence > struct result_ - { - typedef int type; - }; -}; - -} // namespace aux - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct sequence_tag - : aux::sequence_tag_impl< !aux::is_msvc_eti_arg::value > - ::template result_ -{ -}; - -#else - -namespace aux { - -template< bool has_tag_, bool has_begin_ > -struct sequence_tag_impl -{ - // agurt 24/nov/02: MSVC 6.5 gets confused in 'sequence_tag_impl' - // specialization below, if we name it 'result_' here - template< typename Sequence > struct result2_; -}; - -# define AUX_CLASS_SEQUENCE_TAG_SPEC(has_tag, has_begin, result_type) \ -template<> struct sequence_tag_impl \ -{ \ - template< typename Sequence > struct result2_ \ - { \ - typedef result_type type; \ - }; \ -}; \ -/**/ - -AUX_CLASS_SEQUENCE_TAG_SPEC(true, true, typename Sequence::tag) -AUX_CLASS_SEQUENCE_TAG_SPEC(true, false, typename Sequence::tag) -AUX_CLASS_SEQUENCE_TAG_SPEC(false, true, nested_begin_end_tag) -AUX_CLASS_SEQUENCE_TAG_SPEC(false, false, non_sequence_tag) - -# undef AUX_CLASS_SEQUENCE_TAG_SPEC - -} // namespace aux - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct sequence_tag - : aux::sequence_tag_impl< - ::boost::mpl::aux::has_tag::value - , ::boost::mpl::aux::has_begin::value - >::template result2_ -{ -}; - -#endif // BOOST_MSVC - -BOOST_MPL_AUX_NA_SPEC(1, sequence_tag) - -}} - -#endif // BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED diff --git a/boost/mpl/sequence_tag_fwd.hpp b/boost/mpl/sequence_tag_fwd.hpp deleted file mode 100644 index 4b0ed6f..0000000 --- a/boost/mpl/sequence_tag_fwd.hpp +++ /dev/null @@ -1,26 +0,0 @@ - -#ifndef BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED -#define BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -struct nested_begin_end_tag; -struct non_sequence_tag; - -template< typename Sequence > struct sequence_tag; - -}} - -#endif // BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED diff --git a/boost/mpl/size.hpp b/boost/mpl/size.hpp deleted file mode 100644 index 12ffefb..0000000 --- a/boost/mpl/size.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef BOOST_MPL_SIZE_HPP_INCLUDED -#define BOOST_MPL_SIZE_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(Sequence) - > -struct size - : aux::msvc_eti_base< - typename size_impl< typename sequence_tag::type > - ::template apply< Sequence >::type - >::type -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1, size, (Sequence)) -}; - -BOOST_MPL_AUX_NA_SPEC(1, size) - -}} - -#endif // BOOST_MPL_SIZE_HPP_INCLUDED diff --git a/boost/mpl/size_fwd.hpp b/boost/mpl/size_fwd.hpp deleted file mode 100644 index c72628d..0000000 --- a/boost/mpl/size_fwd.hpp +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef BOOST_MPL_SIZE_FWD_HPP_INCLUDED -#define BOOST_MPL_SIZE_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -namespace boost { namespace mpl { - -template< typename Tag > struct size_impl; -template< typename Sequence > struct size; - -}} - -#endif // BOOST_MPL_SIZE_FWD_HPP_INCLUDED diff --git a/boost/mpl/size_t.hpp b/boost/mpl/size_t.hpp deleted file mode 100644 index 99e9b41..0000000 --- a/boost/mpl/size_t.hpp +++ /dev/null @@ -1,25 +0,0 @@ - -#ifndef BOOST_MPL_SIZE_T_HPP_INCLUDED -#define BOOST_MPL_SIZE_T_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include - -#define AUX_WRAPPER_VALUE_TYPE std::size_t -#define AUX_WRAPPER_NAME size_t -#define AUX_WRAPPER_PARAMS(N) std::size_t N - -#include - -#endif // BOOST_MPL_SIZE_T_HPP_INCLUDED diff --git a/boost/mpl/size_t_fwd.hpp b/boost/mpl/size_t_fwd.hpp deleted file mode 100644 index ffdf4b3..0000000 --- a/boost/mpl/size_t_fwd.hpp +++ /dev/null @@ -1,28 +0,0 @@ - -#ifndef BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED -#define BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include // make sure 'size_t' is placed into 'std' -#include - -BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN - -template< std::size_t N > struct size_t; - -BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE -BOOST_MPL_AUX_ADL_BARRIER_DECL(size_t) - -#endif // BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED diff --git a/boost/mpl/sizeof.hpp b/boost/mpl/sizeof.hpp deleted file mode 100644 index cf5e41c..0000000 --- a/boost/mpl/sizeof.hpp +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef BOOST_MPL_SIZEOF_HPP_INCLUDED -#define BOOST_MPL_SIZEOF_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2003 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include - -namespace boost { namespace mpl { - -template< - typename BOOST_MPL_AUX_NA_PARAM(T) - > -struct sizeof_ - : mpl::size_t< sizeof(T) > -{ - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,sizeof_,(T)) -}; - -BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, sizeof_) - -}} - -#endif // BOOST_MPL_SIZEOF_HPP_INCLUDED diff --git a/boost/mpl/transform.hpp b/boost/mpl/transform.hpp deleted file mode 100644 index 4d3e2a0..0000000 --- a/boost/mpl/transform.hpp +++ /dev/null @@ -1,145 +0,0 @@ - -#ifndef BOOST_MPL_TRANSFORM_HPP_INCLUDED -#define BOOST_MPL_TRANSFORM_HPP_INCLUDED - -// Copyright Aleksey Gurtovoy 2000-2004 -// Copyright David Abrahams 2003-2004 -// -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/mpl for documentation. - -// $Id$ -// $Date$ -// $Revision$ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace mpl { - -namespace aux { - -template< - typename Seq - , typename Op - , typename In - > -struct transform1_impl - : fold< - Seq - , typename In::state - , bind2< typename lambda< typename In::operation >::type - , _1 - , bind1< typename lambda::type, _2> - > - > -{ -}; - -template< - typename Seq - , typename Op - , typename In - > -struct reverse_transform1_impl - : reverse_fold< - Seq - , typename In::state - , bind2< typename lambda< typename In::operation >::type - , _1 - , bind1< typename lambda::type, _2> - > - > -{ -}; - -template< - typename Seq1 - , typename Seq2 - , typename Op - , typename In - > -struct transform2_impl - : fold< - pair_view - , typename In::state - , bind2< typename lambda< typename In::operation >::type - , _1 - , bind2< - typename lambda::type - , bind1,_2> - , bind1,_2> - > - > - > -{ -}; - -template< - typename Seq1 - , typename Seq2 - , typename Op - , typename In - > -struct reverse_transform2_impl - : reverse_fold< - pair_view - , typename In::state - , bind2< typename lambda< typename In::operation >::type - , _1 - , bind2< typename lambda< Op >::type - , bind1,_2> - , bind1,_2> - > - > - > -{ -}; - -} // namespace aux - -BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(3, transform1) -BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(4, transform2) - -#define AUX778076_TRANSFORM_DEF(name) \ -template< \ - typename BOOST_MPL_AUX_NA_PARAM(Seq1) \ - , typename BOOST_MPL_AUX_NA_PARAM(Seq2OrOperation) \ - , typename BOOST_MPL_AUX_NA_PARAM(OperationOrInserter) \ - , typename BOOST_MPL_AUX_NA_PARAM(Inserter) \ - > \ -struct name \ -{ \ - typedef typename eval_if< \ - or_< \ - is_na \ - , is_lambda_expression< Seq2OrOperation > \ - , not_< is_sequence > \ - > \ - , name##1 \ - , name##2 \ - >::type type; \ -}; \ -BOOST_MPL_AUX_NA_SPEC(4, name) \ -/**/ - -AUX778076_TRANSFORM_DEF(transform) -AUX778076_TRANSFORM_DEF(reverse_transform) - -#undef AUX778076_TRANSFORM_DEF - -}} - -#endif // BOOST_MPL_TRANSFORM_HPP_INCLUDED diff --git a/boost/next_prior.hpp b/boost/next_prior.hpp index 5de705f..d943b97 100644 --- a/boost/next_prior.hpp +++ b/boost/next_prior.hpp @@ -15,13 +15,12 @@ #ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED #define BOOST_NEXT_PRIOR_HPP_INCLUDED -#include #include -#include #include #include #include #include +#include #include #include @@ -39,46 +38,6 @@ namespace boost { namespace next_prior_detail { -// The trait attempts to detect if the T type is an iterator. Class-type iterators are assumed -// to have the nested type iterator_category. Strictly speaking, this is not required to be the -// case (e.g. a user can specialize iterator_traits for T without defining T::iterator_category). -// Still, this is a good heuristic in practice, and we can't do anything better anyway. -// Since C++17 we can test for iterator_traits::iterator_category presence instead as it is -// required to be only present for iterators. -template< typename T, typename Void = void > -struct is_iterator_class -{ - static BOOST_CONSTEXPR_OR_CONST bool value = false; -}; - -template< typename T > -struct is_iterator_class< - T, - typename enable_if_has_type< -#if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS) - typename std::iterator_traits< T >::iterator_category -#else - typename T::iterator_category -#endif - >::type -> -{ - static BOOST_CONSTEXPR_OR_CONST bool value = true; -}; - -template< typename T > -struct is_iterator : - public is_iterator_class< T > -{ -}; - -template< typename T > -struct is_iterator< T* > -{ - static BOOST_CONSTEXPR_OR_CONST bool value = true; -}; - - template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value > struct next_plus_impl; @@ -107,7 +66,7 @@ struct next_plus_assign_impl< T, Distance, true > } }; -template< typename T, typename Distance, bool IsIterator = is_iterator< T >::value > +template< typename T, typename Distance, bool IsIterator = boost::iterators::is_iterator< T >::value > struct next_advance_impl : public next_plus_assign_impl< T, Distance > { @@ -152,7 +111,7 @@ struct prior_minus_assign_impl< T, Distance, true > } }; -template< typename T, typename Distance, bool IsIterator = is_iterator< T >::value > +template< typename T, typename Distance, bool IsIterator = boost::iterators::is_iterator< T >::value > struct prior_advance_impl : public prior_minus_assign_impl< T, Distance > { diff --git a/boost/optional/detail/old_optional_implementation.hpp b/boost/optional/detail/old_optional_implementation.hpp index 3431e15..6d707fc 100644 --- a/boost/optional/detail/old_optional_implementation.hpp +++ b/boost/optional/detail/old_optional_implementation.hpp @@ -336,7 +336,7 @@ class optional_base : public optional_tag // No-throw (assuming T::~T() doesn't) void reset() BOOST_NOEXCEPT { destroy(); } - // **DEPPRECATED** Replaces the current value -if any- with 'val' + // **DEPRECATED** Replaces the current value -if any- with 'val' void reset ( argument_type val ) { assign(val); } // Returns a pointer to the value if this is initialized, otherwise, @@ -542,7 +542,7 @@ class optional_base : public optional_tag // Thus, the following overload is needed to properly handle the case when the 'lhs' // is another optional. // - // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error // instead of choosing the wrong overload // #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES @@ -629,7 +629,7 @@ class optional_base : public optional_tag // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. // Decent compilers should disallow conversions from reference_content* to T*, but just in case, - // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference. + // the following overloads are used to filter out the case and guarantee an error in case of T being a reference. pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; } pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; } pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; } diff --git a/boost/optional/detail/optional_config.hpp b/boost/optional/detail/optional_config.hpp index 73f2505..b5040a4 100644 --- a/boost/optional/detail/optional_config.hpp +++ b/boost/optional/detail/optional_config.hpp @@ -53,7 +53,7 @@ #endif #if (defined(_MSC_VER) && _MSC_VER <= 1800) -// on MSCV 2013 and earlier an unwanted temporary is created when you assign from +// on MSVC 2013 and earlier an unwanted temporary is created when you assign from // a const lvalue of integral type. Thus we bind not to the original address but // to a temporary. # define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT @@ -114,9 +114,9 @@ #endif -// Detect suport for defaulting move operations +// Detect support for defaulting move operations // (some older compilers implement rvalue references, -// defaulted funcitons but move operations are not special members and cannot be defaulted) +// defaulted functions but move operations are not special members and cannot be defaulted) #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS # define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS diff --git a/boost/optional/detail/optional_reference_spec.hpp b/boost/optional/detail/optional_reference_spec.hpp index 0dfeeef..b013f0b 100644 --- a/boost/optional/detail/optional_reference_spec.hpp +++ b/boost/optional/detail/optional_reference_spec.hpp @@ -66,7 +66,7 @@ void prevent_assignment_from_false_const_integral() { #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES #ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT - // MSVC compiler without rvalue refernces: we need to disable the asignment from + // MSVC compiler without rvalue references: we need to disable the assignment from // const integral lvalue reference, as it may be an invalid temporary BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, "binding const lvalue references to integral types is disabled in this compiler"); @@ -130,7 +130,7 @@ public: explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} - // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with srewed conversion construction from const int + // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int template explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(rhs)) {} diff --git a/boost/optional/detail/optional_relops.hpp b/boost/optional/detail/optional_relops.hpp index 2c17f2b..1c15578 100644 --- a/boost/optional/detail/optional_relops.hpp +++ b/boost/optional/detail/optional_relops.hpp @@ -16,7 +16,7 @@ namespace boost { // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). -// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead. +// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointees() in generic code instead. // diff --git a/boost/optional/detail/optional_trivially_copyable_base.hpp b/boost/optional/detail/optional_trivially_copyable_base.hpp index 5a5b80b..8d98a84 100644 --- a/boost/optional/detail/optional_trivially_copyable_base.hpp +++ b/boost/optional/detail/optional_trivially_copyable_base.hpp @@ -9,7 +9,7 @@ // You are welcome to contact the author at: // akrzemi1@gmail.com -// trivilally-copyable version of the storage +// trivially-copyable version of the storage template class tc_optional_base : public optional_tag @@ -142,7 +142,7 @@ class tc_optional_base : public optional_tag // No-throw (assuming T::~T() doesn't) void reset() BOOST_NOEXCEPT { destroy(); } - // **DEPPRECATED** Replaces the current value -if any- with 'val' + // **DEPRECATED** Replaces the current value -if any- with 'val' void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); } // Returns a pointer to the value if this is initialized, otherwise, @@ -455,7 +455,7 @@ class tc_optional_base : public optional_tag // Thus, the following overload is needed to properly handle the case when the 'lhs' // is another optional. // - // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error // instead of choosing the wrong overload // #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES diff --git a/boost/optional/optional.hpp b/boost/optional/optional.hpp index 4134a7e..56d50d7 100644 --- a/boost/optional/optional.hpp +++ b/boost/optional/optional.hpp @@ -392,7 +392,7 @@ class optional_base : public optional_tag // No-throw (assuming T::~T() doesn't) void reset() BOOST_NOEXCEPT { destroy(); } - // **DEPPRECATED** Replaces the current value -if any- with 'val' + // **DEPRECATED** Replaces the current value -if any- with 'val' void reset ( argument_type val ) { assign(val); } // Returns a pointer to the value if this is initialized, otherwise, @@ -722,7 +722,7 @@ class optional_base : public optional_tag // Thus, the following overload is needed to properly handle the case when the 'lhs' // is another optional. // - // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error // instead of choosing the wrong overload // #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES diff --git a/boost/preprocessor/enum_params_with_a_default.hpp b/boost/preprocessor/enum_params_with_a_default.hpp deleted file mode 100644 index fd1ad4c..0000000 --- a/boost/preprocessor/enum_params_with_a_default.hpp +++ /dev/null @@ -1,17 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_ENUM_PARAMS_WITH_A_DEFAULT_HPP -# define BOOST_PREPROCESSOR_ENUM_PARAMS_WITH_A_DEFAULT_HPP -# -# include -# -# endif diff --git a/boost/preprocessor/repetition.hpp b/boost/preprocessor/repetition.hpp deleted file mode 100644 index efcd60a..0000000 --- a/boost/preprocessor/repetition.hpp +++ /dev/null @@ -1,32 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_HPP -# define BOOST_PREPROCESSOR_REPETITION_HPP -# -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# -# endif diff --git a/boost/preprocessor/repetition/deduce_r.hpp b/boost/preprocessor/repetition/deduce_r.hpp deleted file mode 100644 index 6fe30d6..0000000 --- a/boost/preprocessor/repetition/deduce_r.hpp +++ /dev/null @@ -1,49 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* Revised by Edward Diener (2020) */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_DEDUCE_R_HPP -# define BOOST_PREPROCESSOR_REPETITION_DEDUCE_R_HPP -# -# include -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# -# include -# include -# -# /* BOOST_PP_DEDUCE_R */ -# -# define BOOST_PP_DEDUCE_R() BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256) -# -# else -# -# /* BOOST_PP_DEDUCE_R */ -# -# include -# include -# include -# include -# -# if BOOST_PP_LIMIT_FOR == 256 -# define BOOST_PP_DEDUCE_R() BOOST_PP_DEC(BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256)) -# elif BOOST_PP_LIMIT_FOR == 512 -# define BOOST_PP_DEDUCE_R() BOOST_PP_DEC(BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 512)) -# elif BOOST_PP_LIMIT_FOR == 1024 -# define BOOST_PP_DEDUCE_R() BOOST_PP_DEC(BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 1024)) -# else -# error Incorrect value for the BOOST_PP_LIMIT_FOR limit -# endif -# -# endif -# -# endif diff --git a/boost/preprocessor/repetition/deduce_z.hpp b/boost/preprocessor/repetition/deduce_z.hpp deleted file mode 100644 index 14dedc2..0000000 --- a/boost/preprocessor/repetition/deduce_z.hpp +++ /dev/null @@ -1,22 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_DEDUCE_Z_HPP -# define BOOST_PREPROCESSOR_REPETITION_DEDUCE_Z_HPP -# -# include -# include -# -# /* BOOST_PP_DEDUCE_Z */ -# -# define BOOST_PP_DEDUCE_Z() BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4) -# -# endif diff --git a/boost/preprocessor/repetition/enum_params_with_a_default.hpp b/boost/preprocessor/repetition/enum_params_with_a_default.hpp deleted file mode 100644 index 7496df6..0000000 --- a/boost/preprocessor/repetition/enum_params_with_a_default.hpp +++ /dev/null @@ -1,25 +0,0 @@ -# /* Copyright (C) 2001 -# * Housemarque Oy -# * http://www.housemarque.com -# * -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# */ -# -# /* Revised by Paul Mensonides (2002) */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP -# define BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP -# -# include -# include -# include -# -# /* BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT */ -# -# define BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(count, param, def) BOOST_PP_ENUM_BINARY_PARAMS(count, param, = def BOOST_PP_INTERCEPT) -# -# endif diff --git a/boost/preprocessor/repetition/enum_shifted.hpp b/boost/preprocessor/repetition/enum_shifted.hpp deleted file mode 100644 index d5b006f..0000000 --- a/boost/preprocessor/repetition/enum_shifted.hpp +++ /dev/null @@ -1,68 +0,0 @@ -# /* Copyright (C) 2001 -# * Housemarque Oy -# * http://www.housemarque.com -# * -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# */ -# -# /* Revised by Paul Mensonides (2002) */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_HPP -# define BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_HPP -# -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# -# /* BOOST_PP_ENUM_SHIFTED */ -# -# if 0 -# define BOOST_PP_ENUM_SHIFTED(count, macro, data) -# endif -# -# define BOOST_PP_ENUM_SHIFTED BOOST_PP_CAT(BOOST_PP_ENUM_SHIFTED_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)) -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_SHIFTED_1(c, m, d) BOOST_PP_REPEAT_1(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_1, (m, d)) -# define BOOST_PP_ENUM_SHIFTED_2(c, m, d) BOOST_PP_REPEAT_2(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_2, (m, d)) -# define BOOST_PP_ENUM_SHIFTED_3(c, m, d) BOOST_PP_REPEAT_3(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_3, (m, d)) -# else -# define BOOST_PP_ENUM_SHIFTED_1(c, m, d) BOOST_PP_ENUM_SHIFTED_1_I(c, m, d) -# define BOOST_PP_ENUM_SHIFTED_2(c, m, d) BOOST_PP_ENUM_SHIFTED_1_2(c, m, d) -# define BOOST_PP_ENUM_SHIFTED_3(c, m, d) BOOST_PP_ENUM_SHIFTED_1_3(c, m, d) -# define BOOST_PP_ENUM_SHIFTED_1_I(c, m, d) BOOST_PP_REPEAT_1(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_1, (m, d)) -# define BOOST_PP_ENUM_SHIFTED_2_I(c, m, d) BOOST_PP_REPEAT_2(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_2, (m, d)) -# define BOOST_PP_ENUM_SHIFTED_3_I(c, m, d) BOOST_PP_REPEAT_3(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_3, (m, d)) -# endif -# -# define BOOST_PP_ENUM_SHIFTED_4(c, m, d) BOOST_PP_ERROR(0x0003) -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_ENUM_SHIFTED_M_1(z, n, md) BOOST_PP_ENUM_SHIFTED_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_SHIFTED_M_2(z, n, md) BOOST_PP_ENUM_SHIFTED_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_SHIFTED_M_3(z, n, md) BOOST_PP_ENUM_SHIFTED_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_SHIFTED_M_1_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, im) -# define BOOST_PP_ENUM_SHIFTED_M_2_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, im) -# define BOOST_PP_ENUM_SHIFTED_M_3_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, im) -# else -# define BOOST_PP_ENUM_SHIFTED_M_1(z, n, md) BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# define BOOST_PP_ENUM_SHIFTED_M_2(z, n, md) BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# define BOOST_PP_ENUM_SHIFTED_M_3(z, n, md) BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# endif -# -# define BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d) -# define BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d) -# define BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d) -# -# endif diff --git a/boost/preprocessor/repetition/enum_shifted_binary_params.hpp b/boost/preprocessor/repetition/enum_shifted_binary_params.hpp deleted file mode 100644 index f3d20fc..0000000 --- a/boost/preprocessor/repetition/enum_shifted_binary_params.hpp +++ /dev/null @@ -1,51 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2005. * -# * Distributed under the Boost Software License, Version 1.0. (See * -# * accompanying file LICENSE_1_0.txt or copy at * -# * http://www.boost.org/LICENSE_1_0.txt) * -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_BINARY_PARAMS_HPP -# define BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_BINARY_PARAMS_HPP -# -# include -# include -# include -# include -# include -# include -# include -# include -# -# /* BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(count, p1, p2) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2)) -# else -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(count, p1, p2) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_I(count, p1, p2) -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_I(count, p1, p2) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2)) -# endif -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_IM(z, n, BOOST_PP_TUPLE_REM_2 pp) -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, im) -# else -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, pp), BOOST_PP_TUPLE_ELEM(2, 1, pp)) -# endif -# -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(p1, BOOST_PP_INC(n)) BOOST_PP_CAT(p2, BOOST_PP_INC(n)) -# -# /* BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2)) -# else -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z_I(z, count, p1, p2) -# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z_I(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2)) -# endif -# -# endif diff --git a/boost/preprocessor/repetition/enum_trailing.hpp b/boost/preprocessor/repetition/enum_trailing.hpp deleted file mode 100644 index 20af2d5..0000000 --- a/boost/preprocessor/repetition/enum_trailing.hpp +++ /dev/null @@ -1,63 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_HPP -# define BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_HPP -# -# include -# include -# include -# include -# include -# include -# include -# -# /* BOOST_PP_ENUM_TRAILING */ -# -# if 0 -# define BOOST_PP_ENUM_TRAILING(count, macro, data) -# endif -# -# define BOOST_PP_ENUM_TRAILING BOOST_PP_CAT(BOOST_PP_ENUM_TRAILING_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)) -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_TRAILING_1(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_TRAILING_M_1, (m, d)) -# define BOOST_PP_ENUM_TRAILING_2(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_TRAILING_M_2, (m, d)) -# define BOOST_PP_ENUM_TRAILING_3(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_TRAILING_M_3, (m, d)) -# else -# define BOOST_PP_ENUM_TRAILING_1(c, m, d) BOOST_PP_ENUM_TRAILING_1_I(c, m, d) -# define BOOST_PP_ENUM_TRAILING_2(c, m, d) BOOST_PP_ENUM_TRAILING_2_I(c, m, d) -# define BOOST_PP_ENUM_TRAILING_3(c, m, d) BOOST_PP_ENUM_TRAILING_3_I(c, m, d) -# define BOOST_PP_ENUM_TRAILING_1_I(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_TRAILING_M_1, (m, d)) -# define BOOST_PP_ENUM_TRAILING_2_I(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_TRAILING_M_2, (m, d)) -# define BOOST_PP_ENUM_TRAILING_3_I(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_TRAILING_M_3, (m, d)) -# endif -# -# define BOOST_PP_ENUM_TRAILING_4(c, m, d) BOOST_PP_ERROR(0x0003) -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_ENUM_TRAILING_M_1(z, n, md) BOOST_PP_ENUM_TRAILING_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_TRAILING_M_2(z, n, md) BOOST_PP_ENUM_TRAILING_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_TRAILING_M_3(z, n, md) BOOST_PP_ENUM_TRAILING_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md) -# define BOOST_PP_ENUM_TRAILING_M_1_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_1_I(z, n, im) -# define BOOST_PP_ENUM_TRAILING_M_2_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_2_I(z, n, im) -# define BOOST_PP_ENUM_TRAILING_M_3_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_3_I(z, n, im) -# else -# define BOOST_PP_ENUM_TRAILING_M_1(z, n, md) BOOST_PP_ENUM_TRAILING_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# define BOOST_PP_ENUM_TRAILING_M_2(z, n, md) BOOST_PP_ENUM_TRAILING_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# define BOOST_PP_ENUM_TRAILING_M_3(z, n, md) BOOST_PP_ENUM_TRAILING_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) -# endif -# -# define BOOST_PP_ENUM_TRAILING_M_1_I(z, n, m, d) , m(z, n, d) -# define BOOST_PP_ENUM_TRAILING_M_2_I(z, n, m, d) , m(z, n, d) -# define BOOST_PP_ENUM_TRAILING_M_3_I(z, n, m, d) , m(z, n, d) -# -# endif diff --git a/boost/preprocessor/repetition/enum_trailing_binary_params.hpp b/boost/preprocessor/repetition/enum_trailing_binary_params.hpp deleted file mode 100644 index e201b69..0000000 --- a/boost/preprocessor/repetition/enum_trailing_binary_params.hpp +++ /dev/null @@ -1,53 +0,0 @@ -# /* ************************************************************************** -# * * -# * (C) Copyright Paul Mensonides 2002. -# * Distributed under the Boost Software License, Version 1.0. (See -# * accompanying file LICENSE_1_0.txt or copy at -# * http://www.boost.org/LICENSE_1_0.txt) -# * * -# ************************************************************************** */ -# -# /* See http://www.boost.org for most recent version. */ -# -# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_BINARY_PARAMS_HPP -# define BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_BINARY_PARAMS_HPP -# -# include -# include -# include -# include -# include -# -# /* BOOST_PP_ENUM_TRAILING_BINARY_PARAMS */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2)) -# else -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(count, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_I(count, p1, p2) -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_I(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2)) -# endif -# -# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_IM(z, n, BOOST_PP_TUPLE_REM_2 pp) -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_IM(z, n, im) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, im) -# else -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, pp), BOOST_PP_TUPLE_ELEM(2, 1, pp)) -# endif -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC() -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_II(z, n, p1, p2) -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_II(z, n, p1, p2) , p1 ## n p2 ## n -# else -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, p1, p2) , BOOST_PP_CAT(p1, n) BOOST_PP_CAT(p2, n) -# endif -# -# /* BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z */ -# -# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2)) -# else -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z_I(z, count, p1, p2) -# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z_I(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2)) -# endif -# -# endif diff --git a/boost/process/async_pipe.hpp b/boost/process/async_pipe.hpp new file mode 100644 index 0000000..0982b90 --- /dev/null +++ b/boost/process/async_pipe.hpp @@ -0,0 +1,217 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_PROCESS_ASYNC_PIPE_HPP +#define BOOST_PROCESS_ASYNC_PIPE_HPP + +#include +#include + +#if defined(BOOST_POSIX_API) +#include +#elif defined(BOOST_WINDOWS_API) +#include +#endif + +namespace boost { namespace process { + + +#if defined(BOOST_PROCESS_DOXYGEN) + + +/** Class implementing an asnychronous I/O-Object for use with boost.asio. + * It is based on the corresponding I/O Object, that is either boost::asio::windows::stream_handle or + * boost::asio::posix::stream_descriptor. + * + * It can be used directly with boost::asio::async_read or async_write. + * + * \note The object is copyable, but that does invoke a handle duplicate. + */ +class async_pipe +{ +public: + /** Typedef for the native handle representation. + * \note This is the handle on the system, not the boost.asio class. + * + */ + typedef platform_specific native_handle_type; + /** Typedef for the handle representation of boost.asio. + * + */ + typedef platform_specific handle_type; + + typedef typename handle_type::executor_type executor_type; + + /** Construct a new async_pipe, does automatically open the pipe. + * Initializes source and sink with the same io_context. + * @note Windows creates a named pipe here, where the name is automatically generated. + */ + inline async_pipe(boost::asio::io_context & ios); + + /** Construct a new async_pipe, does automatically open the pipe. + * @note Windows creates a named pipe here, where the name is automatically generated. + */ + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink); + + /** Construct a new async_pipe, does automatically open. + * Initializes source and sink with the same io_context. + * + * @note Windows restricts possible names. + */ + inline async_pipe(boost::asio::io_context & ios, const std::string & name); + + + /** Construct a new async_pipe, does automatically open. + * + * @note Windows restricts possible names. + */ + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, const std::string & name); + + /** Copy-Constructor of the async pipe. + * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown. + * + */ + async_pipe(const async_pipe& lhs); + + /** Move-Constructor of the async pipe. + */ + async_pipe(async_pipe&& lhs); + + /** Construct the async-pipe from a pipe. + * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown. + * + */ + template> + explicit async_pipe(boost::asio::io_context & ios, const basic_pipe & p); + + /** Construct the async-pipe from a pipe, with two different io_context objects. + * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown. + * + */ + template> + explicit async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, + const basic_pipe & p); + + + /** Assign a basic_pipe. + * @note Windows requires a named pipe for this, if a the wrong type is used an exception is thrown. + * + */ + template> + inline async_pipe& operator=(const basic_pipe& p); + + /** Copy Assign a pipe. + * @note Duplicates the handles. + */ + async_pipe& operator=(const async_pipe& lhs); + /** Move assign a pipe */ + async_pipe& operator=(async_pipe&& lhs); + + /** Destructor. Closes the pipe handles. */ + ~async_pipe(); + + /** Explicit cast to basic_pipe. */ + template> + inline explicit operator basic_pipe() const; + + /** Cancel the current asynchronous operations. */ + void cancel(); + /** Close the pipe handles. */ + void close(); + /** Close the pipe handles. While passing an error_code + * + */ + void close(std::error_code & ec); + + /** Check if the pipes are open. */ + bool is_open() const; + + /** Async close, i.e. close after current operation is completed. + * + * \note There is no guarantee that this will indeed read the entire pipe-buffer + */ + void async_close(); + + /** Read some data from the handle. + + * See the boost.asio documentation for more details. + */ + template + std::size_t read_some(const MutableBufferSequence & buffers); + + /** Write some data to the handle. + + * See the boost.asio documentation for more details. + */ + template + std::size_t write_some(const MutableBufferSequence & buffers); + + /** Get the native handle of the source. */ + native_handle native_source() const {return const_cast(_source).native();} + /** Get the native handle of the sink. */ + native_handle native_sink () const {return const_cast(_sink ).native();} + + /** Start an asynchronous read. + * + * See the [boost.asio documentation](http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html) for more details. + */ + template + detail::dummy async_read_some( + const MutableBufferSequence & buffers, + ReadHandler &&handler); + + /** Start an asynchronous write. + + * See the [boost.asio documentation](http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html) for more details. + */ + template + detail::dummy async_write_some( + const ConstBufferSequence & buffers, + WriteHandler && handler); + + ///Get the asio handle of the pipe sink. + const handle_type & sink () const &; + ///Get the asio handle of the pipe source. + const handle_type & source() const &; + + ///Get the asio handle of the pipe sink. Qualified as rvalue + handle_type && sink () &&; + ///Get the asio handle of the pipe source. Qualified as rvalue + handle_type && source() &&; + + /// Move the source out of this class and change the io_context. Qualified as rvalue. \attention Will always move. + handle_type source(::boost::asio::io_context& ios) &&; + /// Move the sink out of this class and change the io_context. Qualified as rvalue. \attention Will always move + handle_type sink (::boost::asio::io_context& ios) &&; + + /// Copy the source out of this class and change the io_context. \attention Will always copy. + handle_type source(::boost::asio::io_context& ios) const &; + /// Copy the sink out of this class and change the io_context. \attention Will always copy + handle_type sink (::boost::asio::io_context& ios) const &; + + + +}; + +#else +using ::boost::process::detail::api::async_pipe; +#endif + + +}} + + + +#endif diff --git a/boost/process/detail/config.hpp b/boost/process/detail/config.hpp new file mode 100644 index 0000000..646daa0 --- /dev/null +++ b/boost/process/detail/config.hpp @@ -0,0 +1,121 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/** + * \file boost/process/config.hpp + * + * Defines various macros. + */ + +#ifndef BOOST_PROCESS_DETAIL_CONFIG_HPP +#define BOOST_PROCESS_DETAIL_CONFIG_HPP + +#include +#include +#include + +#include + +#if defined(BOOST_POSIX_API) +#include +#if defined(__GLIBC__) +#include +#else +extern char **environ; +#endif +#elif defined(BOOST_WINDOWS_API) +#include +#else +#error "System API not supported by boost.process" +#endif + +namespace boost { namespace process { namespace detail +{ + +#if !defined(BOOST_PROCESS_PIPE_SIZE) +#define BOOST_PROCESS_PIPE_SIZE 1024 +#endif + +#if defined(BOOST_POSIX_API) +namespace posix {namespace extensions {}} +namespace api = posix; + +inline std::error_code get_last_error() noexcept +{ + return std::error_code(errno, std::system_category()); +} + +//copied from linux spec. +#if (_XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) +#define BOOST_POSIX_HAS_VFORK 1 +#endif + +#if (_POSIX_C_SOURCE >= 199309L) +#define BOOST_POSIX_HAS_SIGTIMEDWAIT 1 +#endif + +#elif defined(BOOST_WINDOWS_API) +namespace windows {namespace extensions {}} +namespace api = windows; + +inline std::error_code get_last_error() noexcept +{ + return std::error_code(::boost::winapi::GetLastError(), std::system_category()); +} +#endif + +inline void throw_last_error(const std::string & msg) +{ + throw process_error(get_last_error(), msg); +} + +inline void throw_last_error(const char * msg) +{ + throw process_error(get_last_error(), msg); +} + +inline void throw_last_error() +{ + throw process_error(get_last_error()); +} + +inline void throw_error(const std::error_code& ec) +{ + if (ec) + throw process_error(ec); +} + +inline void throw_error(const std::error_code& ec, const char* msg) +{ + if (ec) + throw process_error(ec, msg); +} + +template constexpr Char null_char(); +template<> constexpr char null_char (){return '\0';} +template<> constexpr wchar_t null_char (){return L'\0';} + +template constexpr Char equal_sign(); +template<> constexpr char equal_sign () {return '='; } +template<> constexpr wchar_t equal_sign () {return L'='; } + +template constexpr Char quote_sign(); +template<> constexpr char quote_sign () {return '"'; } +template<> constexpr wchar_t quote_sign () {return L'"'; } + +template constexpr Char space_sign(); +template<> constexpr char space_sign () {return ' '; } +template<> constexpr wchar_t space_sign () {return L' '; } + +} +} +} + +#endif diff --git a/boost/process/detail/posix/async_pipe.hpp b/boost/process/detail/posix/async_pipe.hpp new file mode 100644 index 0000000..ea3bbe0 --- /dev/null +++ b/boost/process/detail/posix/async_pipe.hpp @@ -0,0 +1,365 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_PIPE_HPP_ + + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace process { namespace detail { namespace posix { + +class async_pipe +{ + ::boost::asio::posix::stream_descriptor _source; + ::boost::asio::posix::stream_descriptor _sink ; +public: + typedef int native_handle_type; + typedef ::boost::asio::posix::stream_descriptor handle_type; + typedef typename handle_type::executor_type executor_type; + + executor_type get_executor() + { + return _source.get_executor(); + } + + inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {} + + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink) : _source(ios_source), _sink(ios_sink) + { + int fds[2]; + if (::pipe(fds) == -1) + boost::process::detail::throw_last_error("pipe(2) failed"); + + _source.assign(fds[0]); + _sink .assign(fds[1]); + }; + inline async_pipe(boost::asio::io_context & ios, const std::string & name) + : async_pipe(ios, ios, name) {} + + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & io_sink, const std::string & name); + inline async_pipe(const async_pipe& lhs); + async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink)) + { + lhs._source = ::boost::asio::posix::stream_descriptor{lhs._source.get_executor()}; + lhs._sink = ::boost::asio::posix::stream_descriptor{lhs._sink. get_executor()}; + } + + template> + explicit async_pipe(::boost::asio::io_context & ios_source, + ::boost::asio::io_context & ios_sink, + const basic_pipe & p) + : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink()) + { + } + + template> + explicit async_pipe(boost::asio::io_context & ios, const basic_pipe & p) + : async_pipe(ios, ios, p) + { + } + + template> + inline async_pipe& operator=(const basic_pipe& p); + inline async_pipe& operator=(const async_pipe& rhs); + + inline async_pipe& operator=(async_pipe&& lhs); + + ~async_pipe() + { + boost::system::error_code ec; + close(ec); + } + + template> + inline explicit operator basic_pipe() const; + + void cancel() + { + if (_sink.is_open()) + _sink.cancel(); + if (_source.is_open()) + _source.cancel(); + } + + void close() + { + if (_sink.is_open()) + _sink.close(); + if (_source.is_open()) + _source.close(); + } + void close(boost::system::error_code & ec) + { + if (_sink.is_open()) + _sink.close(ec); + if (_source.is_open()) + _source.close(ec); + } + + + bool is_open() const + { + return _sink.is_open() || _source.is_open(); + } + void async_close() + { + if (_sink.is_open()) + boost::asio::post(_sink.get_executor(), [this]{_sink.close();}); + if (_source.is_open()) + boost::asio::post(_source.get_executor(), [this]{_source.close();}); + } + + template + std::size_t read_some(const MutableBufferSequence & buffers) + { + return _source.read_some(buffers); + } + template + std::size_t write_some(const MutableBufferSequence & buffers) + { + return _sink.write_some(buffers); + } + + template + std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept + { + return _source.read_some(buffers, ec); + } + template + std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept + { + return _sink.write_some(buffers, ec); + } + + + native_handle_type native_source() const {return const_cast(_source).native_handle();} + native_handle_type native_sink () const {return const_cast(_sink ).native_handle();} + + template + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(boost::system::error_code, std::size_t)) + async_read_some( + const MutableBufferSequence & buffers, + ReadHandler &&handler) + { + return _source.async_read_some(buffers, std::forward(handler)); + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(boost::system::error_code, std::size_t)) + async_write_some( + const ConstBufferSequence & buffers, + WriteHandler&& handler) + { + return _sink.async_write_some(buffers, std::forward(handler)); + } + + + const handle_type & sink () const & {return _sink;} + const handle_type & source() const & {return _source;} + + handle_type && sink() && { return std::move(_sink); } + handle_type && source()&& { return std::move(_source); } + + handle_type source(::boost::asio::io_context& ios) && + { + ::boost::asio::posix::stream_descriptor stolen(ios, _source.release()); + return stolen; + } + handle_type sink (::boost::asio::io_context& ios) && + { + ::boost::asio::posix::stream_descriptor stolen(ios, _sink.release()); + return stolen; + } + + handle_type source(::boost::asio::io_context& ios) const & + { + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in)); + } + handle_type sink (::boost::asio::io_context& ios) const & + { + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); + return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in)); + } +}; + + +async_pipe::async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, + const std::string & name) : _source(ios_source), _sink(ios_sink) +{ + auto fifo = mkfifo(name.c_str(), 0666 ); + + if (fifo != 0) + boost::process::detail::throw_last_error("mkfifo() failed"); + + + int read_fd = open(name.c_str(), O_RDWR); + + if (read_fd == -1) + boost::process::detail::throw_last_error(); + + int write_fd = dup(read_fd); + + if (write_fd == -1) + boost::process::detail::throw_last_error(); + + _source.assign(read_fd); + _sink .assign(write_fd); +} + +async_pipe::async_pipe(const async_pipe & p) : + _source(const_cast(p)._source.get_executor()), + _sink( const_cast(p)._sink.get_executor()) +{ + + //cannot get the handle from a const object. + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); + if (source_in == -1) + _source.assign(-1); + else + { + _source.assign(::dup(source_in)); + if (_source.native_handle()== -1) + ::boost::process::detail::throw_last_error("dup()"); + } + + if (sink_in == -1) + _sink.assign(-1); + else + { + _sink.assign(::dup(sink_in)); + if (_sink.native_handle() == -1) + ::boost::process::detail::throw_last_error("dup()"); + } +} + +async_pipe& async_pipe::operator=(const async_pipe & p) +{ + int source; + int sink; + + //cannot get the handle from a const object. + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(p._sink).native_handle(); + if (source_in == -1) + source = -1; + else + { + source = ::dup(source_in); + if (source == -1) + ::boost::process::detail::throw_last_error("dup()"); + } + + if (sink_in == -1) + sink = -1; + else + { + sink = ::dup(sink_in); + if (sink == -1) + ::boost::process::detail::throw_last_error("dup()"); + } + _source.assign(source); + _sink. assign(sink); + + return *this; +} + +async_pipe& async_pipe::operator=(async_pipe && lhs) +{ + std::swap(_source, lhs._source); + std::swap(_sink, lhs._sink); + return *this; +} + +template +async_pipe::operator basic_pipe() const +{ + int source; + int sink; + + //cannot get the handle from a const object. + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); + + + if (source_in == -1) + source = -1; + else + { + source = ::dup(source_in); + if (source == -1) + ::boost::process::detail::throw_last_error("dup()"); + } + + if (sink_in == -1) + sink = -1; + else + { + sink = ::dup(sink_in); + if (sink == -1) + ::boost::process::detail::throw_last_error("dup()"); + } + + return basic_pipe{source, sink}; +} + + +inline bool operator==(const async_pipe & lhs, const async_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +inline bool operator!=(const async_pipe & lhs, const async_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator==(const async_pipe & lhs, const basic_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const async_pipe & lhs, const basic_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator==(const basic_pipe & lhs, const async_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const basic_pipe & lhs, const async_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +}}}} + +#endif /* INCLUDE_BOOST_PIPE_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ */ diff --git a/boost/process/detail/posix/basic_pipe.hpp b/boost/process/detail/posix/basic_pipe.hpp new file mode 100644 index 0000000..50fd4de --- /dev/null +++ b/boost/process/detail/posix/basic_pipe.hpp @@ -0,0 +1,200 @@ +// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_PIPE_HPP +#define BOOST_PROCESS_POSIX_PIPE_HPP + + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace process { namespace detail { namespace posix { + + +template> +class basic_pipe +{ + int _source = -1; + int _sink = -1; +public: + explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {} + explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {} + typedef CharT char_type ; + typedef Traits traits_type; + typedef typename Traits::int_type int_type ; + typedef typename Traits::pos_type pos_type ; + typedef typename Traits::off_type off_type ; + typedef int native_handle_type; + + basic_pipe() + { + int fds[2]; + if (::pipe(fds) == -1) + boost::process::detail::throw_last_error("pipe(2) failed"); + + _source = fds[0]; + _sink = fds[1]; + } + inline basic_pipe(const basic_pipe& rhs); + explicit inline basic_pipe(const std::string& name); + basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink) + { + lhs._source = -1; + lhs._sink = -1; + } + inline basic_pipe& operator=(const basic_pipe& ); + basic_pipe& operator=(basic_pipe&& lhs) + { + _source = lhs._source; + _sink = lhs._sink ; + + lhs._source = -1; + lhs._sink = -1; + + return *this; + } + ~basic_pipe() + { + if (_sink != -1) + ::close(_sink); + if (_source != -1) + ::close(_source); + } + native_handle_type native_source() const {return _source;} + native_handle_type native_sink () const {return _sink;} + + void assign_source(native_handle_type h) { _source = h;} + void assign_sink (native_handle_type h) { _sink = h;} + + int_type write(const char_type * data, int_type count) + { + ssize_t write_len; + while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1) + { + //Try again if interrupted + auto err = errno; + if (err != EINTR) + ::boost::process::detail::throw_last_error(); + } + return static_cast(write_len); + } + int_type read(char_type * data, int_type count) + { + ssize_t read_len; + while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1) + { + //Try again if interrupted + auto err = errno; + if (err != EINTR) + ::boost::process::detail::throw_last_error(); + } + return static_cast(read_len); + } + + bool is_open() const + { + return (_source != -1) || + (_sink != -1); + } + + void close() + { + if (_source != -1) + ::close(_source); + if (_sink != -1) + ::close(_sink); + _source = -1; + _sink = -1; + } +}; + +template +basic_pipe::basic_pipe(const basic_pipe & rhs) +{ + if (rhs._source != -1) + { + _source = ::dup(rhs._source); + if (_source == -1) + ::boost::process::detail::throw_last_error("dup() failed"); + } + if (rhs._sink != -1) + { + _sink = ::dup(rhs._sink); + if (_sink == -1) + ::boost::process::detail::throw_last_error("dup() failed"); + + } +} + +template +basic_pipe &basic_pipe::operator=(const basic_pipe & rhs) +{ + if (rhs._source != -1) + { + _source = ::dup(rhs._source); + if (_source == -1) + ::boost::process::detail::throw_last_error("dup() failed"); + } + if (rhs._sink != -1) + { + _sink = ::dup(rhs._sink); + if (_sink == -1) + ::boost::process::detail::throw_last_error("dup() failed"); + + } + return *this; +} + + +template +basic_pipe::basic_pipe(const std::string & name) +{ + auto fifo = mkfifo(name.c_str(), 0666 ); + + if (fifo != 0) + boost::process::detail::throw_last_error("mkfifo() failed"); + + + int read_fd = open(name.c_str(), O_RDWR); + + if (read_fd == -1) + boost::process::detail::throw_last_error(); + + int write_fd = dup(read_fd); + + if (write_fd == -1) + boost::process::detail::throw_last_error(); + + _sink = write_fd; + _source = read_fd; + ::unlink(name.c_str()); +} + +template +inline bool operator==(const basic_pipe & lhs, const basic_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const basic_pipe & lhs, const basic_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +}}}} + +#endif diff --git a/boost/process/detail/posix/compare_handles.hpp b/boost/process/detail/posix/compare_handles.hpp new file mode 100644 index 0000000..6347572 --- /dev/null +++ b/boost/process/detail/posix/compare_handles.hpp @@ -0,0 +1,42 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ + + +#include +#include +#include +#include + +namespace boost { namespace process { namespace detail { namespace posix { + + +inline bool compare_handles(int lhs, int rhs) +{ + + if ((lhs == -1) || (rhs == -1)) + return false; + + if (lhs == rhs) + return true; + + struct stat stat1, stat2; + if(fstat(lhs, &stat1) < 0) ::boost::process::detail::throw_last_error("fstat() failed"); + if(fstat(rhs, &stat2) < 0) ::boost::process::detail::throw_last_error("fstat() failed"); + + return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); +} + + + + + +}}}} + + + +#endif /* BOOST_PROCESS_DETAIL_POSIX_COMPARE_HANDLES_HPP_ */ diff --git a/boost/process/detail/windows/async_pipe.hpp b/boost/process/detail/windows/async_pipe.hpp new file mode 100644 index 0000000..0b447f9 --- /dev/null +++ b/boost/process/detail/windows/async_pipe.hpp @@ -0,0 +1,485 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ +#define BOOST_PROCESS_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace process { namespace detail { namespace windows { + +inline std::string make_pipe_name() +{ + std::string name = "\\\\.\\pipe\\boost_process_auto_pipe_"; + + auto pid = ::boost::winapi::GetCurrentProcessId(); + + static std::atomic_size_t cnt{0}; + name += std::to_string(pid); + name += "_"; + name += std::to_string(cnt++); + + return name; +} + +class async_pipe +{ + ::boost::asio::windows::stream_handle _source; + ::boost::asio::windows::stream_handle _sink ; + + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, + const std::string & name, bool private_); + +public: + typedef ::boost::winapi::HANDLE_ native_handle_type; + typedef ::boost::asio::windows::stream_handle handle_type; + typedef typename handle_type::executor_type executor_type; + + async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios, make_pipe_name(), true) {} + async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink) + : async_pipe(ios_source, ios_sink, make_pipe_name(), true) {} + + async_pipe(boost::asio::io_context & ios, const std::string & name) + : async_pipe(ios, ios, name, false) {} + + async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink, const std::string & name) + : async_pipe(ios_source, ios_sink, name, false) {} + + + + inline async_pipe(const async_pipe& rhs); + async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink)) + { + } + template> + explicit async_pipe(::boost::asio::io_context & ios_source, + ::boost::asio::io_context & ios_sink, + const basic_pipe & p) + : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink()) + { + } + + template> + explicit async_pipe(boost::asio::io_context & ios, const basic_pipe & p) + : async_pipe(ios, ios, p) + { + } + + template> + inline async_pipe& operator=(const basic_pipe& p); + inline async_pipe& operator=(const async_pipe& rhs); + + inline async_pipe& operator=(async_pipe&& rhs); + + ~async_pipe() + { + boost::system::error_code ec; + close(ec); + } + + template> + inline explicit operator basic_pipe() const; + + void cancel() + { + if (_sink.is_open()) + _sink.cancel(); + if (_source.is_open()) + _source.cancel(); + } + + void close() + { + if (_sink.is_open()) + { + _sink.close(); + _sink = handle_type(_sink.get_executor()); + } + if (_source.is_open()) + { + _source.close(); + _source = handle_type(_source.get_executor()); + } + } + void close(boost::system::error_code & ec) + { + if (_sink.is_open()) + { + _sink.close(ec); + _sink = handle_type(_sink.get_executor()); + } + if (_source.is_open()) + { + _source.close(ec); + _source = handle_type(_source.get_executor()); + } + } + + bool is_open() const + { + return _sink.is_open() || _source.is_open(); + } + void async_close() + { + if (_sink.is_open()) + boost::asio::post(_sink.get_executor(), [this]{_sink.close();}); + if (_source.is_open()) + boost::asio::post(_source.get_executor(), [this]{_source.close();}); + } + + template + std::size_t read_some(const MutableBufferSequence & buffers) + { + return _source.read_some(buffers); + } + template + std::size_t write_some(const MutableBufferSequence & buffers) + { + return _sink.write_some(buffers); + } + + + template + std::size_t read_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept + { + return _source.read_some(buffers, ec); + } + template + std::size_t write_some(const MutableBufferSequence & buffers, boost::system::error_code & ec) noexcept + { + return _sink.write_some(buffers, ec); + } + + native_handle_type native_source() const {return const_cast(_source).native_handle();} + native_handle_type native_sink () const {return const_cast(_sink ).native_handle();} + + template + BOOST_ASIO_INITFN_RESULT_TYPE( + ReadHandler, void(boost::system::error_code, std::size_t)) + async_read_some( + const MutableBufferSequence & buffers, + ReadHandler &&handler) + { + return _source.async_read_some(buffers, std::forward(handler)); + } + + template + BOOST_ASIO_INITFN_RESULT_TYPE( + WriteHandler, void(boost::system::error_code, std::size_t)) + async_write_some( + const ConstBufferSequence & buffers, + WriteHandler && handler) + { + return _sink.async_write_some(buffers, std::forward(handler)); + } + + const handle_type & sink () const & {return _sink;} + const handle_type & source() const & {return _source;} + + handle_type && source() && { return std::move(_source); } + handle_type && sink() && { return std::move(_sink); } + + handle_type source(::boost::asio::io_context& ios) && + { + ::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle()); + boost::system::error_code ec; + _source.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec); + return stolen; + } + handle_type sink (::boost::asio::io_context& ios) && + { + ::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle()); + boost::system::error_code ec; + _sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec); + return stolen; + } + + handle_type source(::boost::asio::io_context& ios) const & + { + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ source; + auto source_in = const_cast(_source).native_handle(); + if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, source_in, proc, &source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + return ::boost::asio::windows::stream_handle(ios.get_executor(), source); + } + handle_type sink (::boost::asio::io_context& ios) const & + { + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ sink; + auto sink_in = const_cast(_sink).native_handle(); + if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, sink_in, proc, &sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + return ::boost::asio::windows::stream_handle(ios.get_executor(), sink); + } +}; + +async_pipe::async_pipe(const async_pipe& p) : + _source(const_cast(p._source).get_executor()), + _sink (const_cast(p._sink).get_executor()) +{ + + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ source; + ::boost::winapi::HANDLE_ sink; + + //cannot get the handle from a const object. + auto source_in = const_cast(p._source).native_handle(); + auto sink_in = const_cast(p._sink).native_handle(); + + if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, source_in, proc, &source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, sink_in, proc, &sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (source != ::boost::winapi::INVALID_HANDLE_VALUE_) + _source.assign(source); + if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_) + _sink. assign(sink); +} + + +async_pipe::async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, + const std::string & name, bool private_) : _source(ios_source), _sink(ios_sink) +{ + static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary + + ::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe( +#if defined(BOOST_NO_ANSI_APIS) + ::boost::process::detail::convert(name).c_str(), +#else + name.c_str(), +#endif + ::boost::winapi::PIPE_ACCESS_INBOUND_ + | FILE_FLAG_OVERLAPPED_, //write flag + 0, private_ ? 1 : ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr); + + + if (source == boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::process::detail::throw_last_error("create_named_pipe(" + name + ") failed"); + + _source.assign(source); + + ::boost::winapi::HANDLE_ sink = boost::winapi::create_file( +#if defined(BOOST_NO_ANSI_APIS) + ::boost::process::detail::convert(name).c_str(), +#else + name.c_str(), +#endif + ::boost::winapi::GENERIC_WRITE_, 0, nullptr, + ::boost::winapi::OPEN_EXISTING_, + FILE_FLAG_OVERLAPPED_, //to allow read + nullptr); + + if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::process::detail::throw_last_error("create_file() failed"); + + _sink.assign(sink); +} + +template +async_pipe& async_pipe::operator=(const basic_pipe & p) +{ + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ source; + ::boost::winapi::HANDLE_ sink; + + //cannot get the handle from a const object. + auto source_in = p.native_source(); + auto sink_in = p.native_sink(); + + if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, source_in.native_handle(), proc, &source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, sink_in.native_handle(), proc, &sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + //so we also assign the io_context + if (source != ::boost::winapi::INVALID_HANDLE_VALUE_) + _source.assign(source); + + if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_) + _sink.assign(sink); + + return *this; +} + +async_pipe& async_pipe::operator=(const async_pipe & p) +{ + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ source; + ::boost::winapi::HANDLE_ sink; + + //cannot get the handle from a const object. + auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source); + auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink); + + source_in.get_executor(); + + if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_) + source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, source_in.native_handle(), proc, &source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (sink_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_) + sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, sink_in.native_handle(), proc, &sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + //so we also assign the io_context + if (source != ::boost::winapi::INVALID_HANDLE_VALUE_) + _source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source); + else + _source = ::boost::asio::windows::stream_handle(source_in.get_executor()); + + if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_) + _sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink); + else + _sink = ::boost::asio::windows::stream_handle(source_in.get_executor()); + + return *this; +} + +async_pipe& async_pipe::operator=(async_pipe && rhs) +{ + _source = std::move(rhs._source); + _sink = std::move(rhs._sink); + return *this; +} + +template +async_pipe::operator basic_pipe() const +{ + auto proc = ::boost::winapi::GetCurrentProcess(); + + ::boost::winapi::HANDLE_ source; + ::boost::winapi::HANDLE_ sink; + + //cannot get the handle from a const object. + auto source_in = const_cast<::boost::asio::windows::stream_handle &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::windows::stream_handle &>(_sink).native_handle(); + + if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, source_in, proc, &source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_) + sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, sink_in, proc, &sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + return basic_pipe{source, sink}; +} + +inline bool operator==(const async_pipe & lhs, const async_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +inline bool operator!=(const async_pipe & lhs, const async_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator==(const async_pipe & lhs, const basic_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const async_pipe & lhs, const basic_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator==(const basic_pipe & lhs, const async_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const basic_pipe & lhs, const async_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +}}}} + +#endif /* INCLUDE_BOOST_PIPE_DETAIL_WINDOWS_ASYNC_PIPE_HPP_ */ diff --git a/boost/process/detail/windows/basic_pipe.hpp b/boost/process/detail/windows/basic_pipe.hpp new file mode 100644 index 0000000..0fe524d --- /dev/null +++ b/boost/process/detail/windows/basic_pipe.hpp @@ -0,0 +1,230 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP +#define BOOST_PROCESS_DETAIL_WINDOWS_PIPE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace process { namespace detail { namespace windows { + +template> +class basic_pipe +{ + ::boost::winapi::HANDLE_ _source = ::boost::winapi::INVALID_HANDLE_VALUE_; + ::boost::winapi::HANDLE_ _sink = ::boost::winapi::INVALID_HANDLE_VALUE_; +public: + typedef CharT char_type ; + typedef Traits traits_type; + typedef typename Traits::int_type int_type ; + typedef typename Traits::pos_type pos_type ; + typedef typename Traits::off_type off_type ; + typedef ::boost::winapi::HANDLE_ native_handle_type; + + explicit basic_pipe(::boost::winapi::HANDLE_ source, ::boost::winapi::HANDLE_ sink) + : _source(source), _sink(sink) {} + inline explicit basic_pipe(const std::string & name); + inline basic_pipe(const basic_pipe& p); + basic_pipe(basic_pipe&& lhs) : _source(lhs._source), _sink(lhs._sink) + { + lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_; + lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + } + inline basic_pipe& operator=(const basic_pipe& p); + inline basic_pipe& operator=(basic_pipe&& lhs); + ~basic_pipe() + { + if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::winapi::CloseHandle(_sink); + if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::winapi::CloseHandle(_source); + } + native_handle_type native_source() const {return _source;} + native_handle_type native_sink () const {return _sink;} + + void assign_source(native_handle_type h) { _source = h;} + void assign_sink (native_handle_type h) { _sink = h;} + + basic_pipe() + { + if (!::boost::winapi::CreatePipe(&_source, &_sink, nullptr, 0)) + throw_last_error("CreatePipe() failed"); + + } + + int_type write(const char_type * data, int_type count) + { + ::boost::winapi::DWORD_ write_len; + if (!::boost::winapi::WriteFile( + _sink, data, count * sizeof(char_type), &write_len, nullptr + )) + { + auto ec = ::boost::process::detail::get_last_error(); + if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) || + (ec.value() == ::boost::winapi::ERROR_NO_DATA_)) + return 0; + else + throw process_error(ec, "WriteFile failed"); + } + return static_cast(write_len); + } + int_type read(char_type * data, int_type count) + { + ::boost::winapi::DWORD_ read_len; + if (!::boost::winapi::ReadFile( + _source, data, count * sizeof(char_type), &read_len, nullptr + )) + { + auto ec = ::boost::process::detail::get_last_error(); + if ((ec.value() == ::boost::winapi::ERROR_BROKEN_PIPE_) || + (ec.value() == ::boost::winapi::ERROR_NO_DATA_)) + return 0; + else + throw process_error(ec, "ReadFile failed"); + } + return static_cast(read_len); + } + + bool is_open() const + { + return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) || + (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_); + } + + void close() + { + ::boost::winapi::CloseHandle(_source); + ::boost::winapi::CloseHandle(_sink); + _source = ::boost::winapi::INVALID_HANDLE_VALUE_; + _sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + } +}; + +template +basic_pipe::basic_pipe(const basic_pipe & p) +{ + auto proc = ::boost::winapi::GetCurrentProcess(); + + if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_) + _source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, p._source, proc, &_source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_) + _sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, p._sink, proc, &_sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + +} + +template +basic_pipe::basic_pipe(const std::string & name) +{ + static constexpr int OPEN_EXISTING_ = 3; //temporary. + static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary + //static constexpr int FILE_ATTRIBUTE_NORMAL_ = 0x00000080; //temporary + +#if BOOST_NO_ANSI_APIS + std::wstring name_ = boost::process::detail::convert(name); +#else + auto &name_ = name; +#endif + ::boost::winapi::HANDLE_ source = ::boost::winapi::create_named_pipe( + name_.c_str(), + ::boost::winapi::PIPE_ACCESS_INBOUND_ + | FILE_FLAG_OVERLAPPED_, //write flag + 0, ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr); + + if (source == boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::process::detail::throw_last_error("create_named_pipe() failed"); + + ::boost::winapi::HANDLE_ sink = boost::winapi::create_file( + name_.c_str(), + ::boost::winapi::GENERIC_WRITE_, 0, nullptr, + OPEN_EXISTING_, + FILE_FLAG_OVERLAPPED_, //to allow read + nullptr); + + if (sink == ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::process::detail::throw_last_error("create_file() failed"); + + _source = source; + _sink = sink; +} + +template +basic_pipe& basic_pipe::operator=(const basic_pipe & p) +{ + auto proc = ::boost::winapi::GetCurrentProcess(); + + if (p._source == ::boost::winapi::INVALID_HANDLE_VALUE_) + _source = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, p._source, proc, &_source, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + if (p._sink == ::boost::winapi::INVALID_HANDLE_VALUE_) + _sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + else if (!::boost::winapi::DuplicateHandle( + proc, p._sink, proc, &_sink, 0, + static_cast<::boost::winapi::BOOL_>(true), + ::boost::winapi::DUPLICATE_SAME_ACCESS_)) + throw_last_error("Duplicate Pipe Failed"); + + return *this; +} + +template +basic_pipe& basic_pipe::operator=(basic_pipe && lhs) +{ + if (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::winapi::CloseHandle(_source); + + if (_sink != ::boost::winapi::INVALID_HANDLE_VALUE_) + ::boost::winapi::CloseHandle(_sink); + + _source = lhs._source; + _sink = lhs._sink; + lhs._source = ::boost::winapi::INVALID_HANDLE_VALUE_; + lhs._sink = ::boost::winapi::INVALID_HANDLE_VALUE_; + return *this; +} + +template +inline bool operator==(const basic_pipe & lhs, const basic_pipe & rhs) +{ + return compare_handles(lhs.native_source(), rhs.native_source()) && + compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +template +inline bool operator!=(const basic_pipe & lhs, const basic_pipe & rhs) +{ + return !compare_handles(lhs.native_source(), rhs.native_source()) || + !compare_handles(lhs.native_sink(), rhs.native_sink()); +} + +}}}} + +#endif diff --git a/boost/process/detail/windows/compare_handles.hpp b/boost/process/detail/windows/compare_handles.hpp new file mode 100644 index 0000000..0336149 --- /dev/null +++ b/boost/process/detail/windows/compare_handles.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_ +#define BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_ + +#include +#include +#include + +namespace boost { namespace process { namespace detail { namespace windows { + +inline bool compare_handles(boost::winapi::HANDLE_ lhs, boost::winapi::HANDLE_ rhs) +{ + if ( (lhs == ::boost::winapi::INVALID_HANDLE_VALUE_) + || (rhs == ::boost::winapi::INVALID_HANDLE_VALUE_)) + return false; + + if (lhs == rhs) + return true; + + ::boost::winapi::BY_HANDLE_FILE_INFORMATION_ lhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0}; + ::boost::winapi::BY_HANDLE_FILE_INFORMATION_ rhs_info{0,{0,0},{0,0},{0,0},0,0,0,0,0,0}; + + if (!::boost::winapi::GetFileInformationByHandle(lhs, &lhs_info)) + ::boost::process::detail::throw_last_error("GetFileInformationByHandle"); + + if (!::boost::winapi::GetFileInformationByHandle(rhs, &rhs_info)) + ::boost::process::detail::throw_last_error("GetFileInformationByHandle"); + + return (lhs_info.nFileIndexHigh == rhs_info.nFileIndexHigh) + && (lhs_info.nFileIndexLow == rhs_info.nFileIndexLow); +} + +}}}} + + + +#endif /* BOOST_PROCESS_DETAIL_WINDOWS_COMPARE_HANDLES_HPP_ */ diff --git a/boost/process/exception.hpp b/boost/process/exception.hpp new file mode 100644 index 0000000..1bb3911 --- /dev/null +++ b/boost/process/exception.hpp @@ -0,0 +1,30 @@ +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_EXCEPTION_HPP_ +#define BOOST_PROCESS_EXCEPTION_HPP_ + +#include + +namespace boost +{ +namespace process +{ +///The exception usually thrown by boost.process. +/** It merely inherits [std::system_error](http://en.cppreference.com/w/cpp/error/system_error) + * but can then be distinguished in the catch-block from other system errors. + * + */ +struct process_error : std::system_error +{ + using std::system_error::system_error; +}; + +} +} + + + +#endif /* BOOST_PROCESS_EXCEPTION_HPP_ */ diff --git a/boost/process/filesystem.hpp b/boost/process/filesystem.hpp new file mode 100644 index 0000000..4e1c12e --- /dev/null +++ b/boost/process/filesystem.hpp @@ -0,0 +1,28 @@ +// Copyright (c) 2021 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_PROCESS_FILESYSTEM_HPP +#define BOOST_PROCESS_FILESYSTEM_HPP + +#ifdef BOOST_PROCESS_USE_STD_FS +#include +#else +#include +#include +#endif + +namespace boost +{ +namespace process +{ +#ifdef BOOST_PROCESS_USE_STD_FS +namespace filesystem = std::filesystem; +#else +namespace filesystem = boost::filesystem; +#endif + +} +} + +#endif //BOOST_PROCESS_FILESYSTEM_HPP diff --git a/boost/range/algorithm/adjacent_find.hpp b/boost/range/algorithm/adjacent_find.hpp deleted file mode 100644 index 1b88dae..0000000 --- a/boost/range/algorithm/adjacent_find.hpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function adjacent_find -/// -/// range-based version of the adjacent_find std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< typename ForwardRange > -inline typename range_iterator::type -adjacent_find(ForwardRange & rng) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return std::adjacent_find(boost::begin(rng),boost::end(rng)); -} - -/// \overload -template< typename ForwardRange > -inline typename range_iterator::type -adjacent_find(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return std::adjacent_find(boost::begin(rng),boost::end(rng)); -} - -/// \overload -template< typename ForwardRange, typename BinaryPredicate > -inline typename range_iterator::type -adjacent_find(ForwardRange & rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - typename range_value::type>)); - return std::adjacent_find(boost::begin(rng),boost::end(rng),pred); -} - -/// \overload -template< typename ForwardRange, typename BinaryPredicate > -inline typename range_iterator::type -adjacent_find(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - typename range_value::type>)); - return std::adjacent_find(boost::begin(rng),boost::end(rng),pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, typename ForwardRange > -inline typename range_return::type -adjacent_find(ForwardRange & rng) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_return:: - pack(std::adjacent_find(boost::begin(rng),boost::end(rng)), - rng); -} - -/// \overload -template< range_return_value re, typename ForwardRange > -inline typename range_return::type -adjacent_find(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_return:: - pack(std::adjacent_find(boost::begin(rng),boost::end(rng)), - rng); -} - -/// \overload -template< range_return_value re, typename ForwardRange, typename BinaryPredicate > -inline typename range_return::type -adjacent_find(ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - typename range_value::type>)); - return range_return:: - pack(std::adjacent_find(boost::begin(rng),boost::end(rng),pred), - rng); -} - -/// \overload -template< range_return_value re, typename ForwardRange, typename BinaryPredicate > -inline typename range_return::type -adjacent_find(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_return:: - pack(std::adjacent_find(boost::begin(rng),boost::end(rng),pred), - rng); -} - - } // namespace range - using range::adjacent_find; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/binary_search.hpp b/boost/range/algorithm/binary_search.hpp deleted file mode 100644 index bb64ec8..0000000 --- a/boost/range/algorithm/binary_search.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function binary_search -/// -/// range-based version of the binary_search std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline bool binary_search(const ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::binary_search(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template -inline bool binary_search(const ForwardRange& rng, const Value& val, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::binary_search(boost::begin(rng), boost::end(rng), val, pred); -} - - } // namespace range - using range::binary_search; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/copy.hpp b/boost/range/algorithm/copy.hpp deleted file mode 100644 index f15b31f..0000000 --- a/boost/range/algorithm/copy.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function copy -/// -/// range-based version of the copy std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre OutputIterator is a model of the OutputIteratorConcept -template< class SinglePassRange, class OutputIterator > -inline OutputIterator copy(const SinglePassRange& rng, OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::copy(boost::begin(rng),boost::end(rng),out); -} - - } // namespace range - using range::copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/copy_backward.hpp b/boost/range/algorithm/copy_backward.hpp deleted file mode 100644 index c95c6f1..0000000 --- a/boost/range/algorithm/copy_backward.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_COPY_BACKWARD_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_COPY_BACKWARD_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function copy_backward -/// -/// range-based version of the copy_backwards std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept -/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept -template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator > -inline BidirectionalTraversalWriteableIterator -copy_backward(const BidirectionalRange& rng, - BidirectionalTraversalWriteableIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::copy_backward(boost::begin(rng), boost::end(rng), out); -} - - } // namespace range - using range::copy_backward; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/count.hpp b/boost/range/algorithm/count.hpp deleted file mode 100644 index 8316ce0..0000000 --- a/boost/range/algorithm/count.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_COUNT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_COUNT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function count -/// -/// range-based version of the count std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -template< class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_difference::type -count(SinglePassRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::count(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_difference::type -count(const SinglePassRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::count(boost::begin(rng), boost::end(rng), val); -} - - } // namespace range - using range::count; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/count_if.hpp b/boost/range/algorithm/count_if.hpp deleted file mode 100644 index ae17b0e..0000000 --- a/boost/range/algorithm/count_if.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_COUNT_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_COUNT_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function count_if -/// -/// range-based version of the count_if std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre UnaryPredicate is a model of the UnaryPredicateConcept -template< class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME boost::range_difference::type -count_if(SinglePassRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::count_if(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template< class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME boost::range_difference::type -count_if(const SinglePassRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::count_if(boost::begin(rng), boost::end(rng), pred); -} - - } // namespace range - using range::count_if; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/equal_range.hpp b/boost/range/algorithm/equal_range.hpp deleted file mode 100644 index 4aa4a54..0000000 --- a/boost/range/algorithm/equal_range.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function equal_range -/// -/// range-based version of the equal_range std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre SortPredicate is a model of the BinaryPredicateConcept -template -inline std::pair< - BOOST_DEDUCED_TYPENAME boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type - > -equal_range(ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::equal_range(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template -inline std::pair< - BOOST_DEDUCED_TYPENAME boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type - > -equal_range(const ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::equal_range(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template -inline std::pair< - BOOST_DEDUCED_TYPENAME boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type - > -equal_range(ForwardRange& rng, const Value& val, SortPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::equal_range(boost::begin(rng), boost::end(rng), val, pred); -} - -/// \overload -template -inline std::pair< - BOOST_DEDUCED_TYPENAME boost::range_iterator::type, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type - > -equal_range(const ForwardRange& rng, const Value& val, SortPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::equal_range(boost::begin(rng), boost::end(rng), val, pred); -} - - } // namespace range - using range::equal_range; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/fill.hpp b/boost/range/algorithm/fill.hpp deleted file mode 100644 index 95231a8..0000000 --- a/boost/range/algorithm/fill.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FILL_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FILL_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function fill -/// -/// range-based version of the fill std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class Value > -inline ForwardRange& fill(ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::fill(boost::begin(rng), boost::end(rng), val); - return rng; -} - -/// \overload -template< class ForwardRange, class Value > -inline const ForwardRange& fill(const ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::fill(boost::begin(rng), boost::end(rng), val); - return rng; -} - - } // namespace range - using range::fill; -} - -#endif // include guard diff --git a/boost/range/algorithm/fill_n.hpp b/boost/range/algorithm/fill_n.hpp deleted file mode 100644 index 02a0c2a..0000000 --- a/boost/range/algorithm/fill_n.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FILL_N_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FILL_N_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function fill_n -/// -/// range-based version of the fill_n std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre n <= std::distance(boost::begin(rng), boost::end(rng)) -template< class ForwardRange, class Size, class Value > -inline ForwardRange& fill_n(ForwardRange& rng, Size n, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_ASSERT( static_cast(std::distance(boost::begin(rng), boost::end(rng))) >= n ); - std::fill_n(boost::begin(rng), n, val); - return rng; -} - -/// \overload -template< class ForwardRange, class Size, class Value > -inline const ForwardRange& fill_n(const ForwardRange& rng, Size n, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_ASSERT( static_cast(std::distance(boost::begin(rng), boost::end(rng))) >= n ); - std::fill_n(boost::begin(rng), n, val); - return rng; -} - - } // namespace range - using range::fill_n; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/find.hpp b/boost/range/algorithm/find.hpp deleted file mode 100644 index 72c5cf1..0000000 --- a/boost/range/algorithm/find.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FIND_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FIND_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function find -/// -/// range-based version of the find std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -template< class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -find( SinglePassRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::find(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -find( const SinglePassRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::find(boost::begin(rng), boost::end(rng), val); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find( SinglePassRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return range_return:: - pack(std::find(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class SinglePassRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -find( const SinglePassRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return range_return:: - pack(std::find(boost::begin(rng), boost::end(rng), val), - rng); -} - - } // namespace range - using range::find; -} - -#endif // include guard diff --git a/boost/range/algorithm/find_end.hpp b/boost/range/algorithm/find_end.hpp deleted file mode 100644 index 757e999..0000000 --- a/boost/range/algorithm/find_end.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FIND_END_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FIND_END_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function find_end -/// -/// range-based version of the find_end std algorithm -/// -/// \pre ForwardRange1 is a model of the ForwardRangeConcept -/// \pre ForwardRange2 is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator< ForwardRange1 >::type ->::type -find_end(ForwardRange1 & rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_end(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_iterator< const ForwardRange1 >::type -find_end(const ForwardRange1 & rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_end(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -find_end(ForwardRange1 & rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_end(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -find_end(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_end(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find_end(ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_end(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_return::type -find_end(const ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_end(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find_end(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_end(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -find_end(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_end(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred), - rng1); -} - - } // namespace range - using range::find_end; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/find_first_of.hpp b/boost/range/algorithm/find_first_of.hpp deleted file mode 100644 index 4cb5989..0000000 --- a/boost/range/algorithm/find_first_of.hpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function find_first_of -/// -/// range-based version of the find_first_of std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre ForwardRange2 is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< class SinglePassRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -find_first_of(SinglePassRange1 & rng1, ForwardRange2 const & rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_first_of(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template< class SinglePassRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_first_of(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template< class SinglePassRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -find_first_of(SinglePassRange1 & rng1, ForwardRange2 const & rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_first_of(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred); -} - -/// \overload -template< class SinglePassRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return std::find_first_of(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred); -} - -// range return overloads -/// \overload -template< range_return_value re, class SinglePassRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class SinglePassRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_return::type -find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class SinglePassRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find_first_of(SinglePassRange1 & rng1, const ForwardRange2& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred), - rng1); -} - -/// \overload -template< range_return_value re, class SinglePassRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -find_first_of(const SinglePassRange1 & rng1, const ForwardRange2& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - - return range_return:: - pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred), - rng1); -} - - } // namespace range - using range::find_first_of; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/find_if.hpp b/boost/range/algorithm/find_if.hpp deleted file mode 100644 index 2d1926d..0000000 --- a/boost/range/algorithm/find_if.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FIND_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FIND_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function find_if -/// -/// range-based version of the find_if std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre UnaryPredicate is a model of the UnaryPredicateConcept -template< class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -find_if( SinglePassRange& rng, UnaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::find_if(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template< class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -find_if( const SinglePassRange& rng, UnaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::find_if(boost::begin(rng), boost::end(rng), pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -find_if( SinglePassRange& rng, UnaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return range_return:: - pack(std::find_if(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template< range_return_value re, class SinglePassRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -find_if( const SinglePassRange& rng, UnaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return range_return:: - pack(std::find_if(boost::begin(rng), boost::end(rng), pred), - rng); -} - - } // namespace range - using range::find_if; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/for_each.hpp b/boost/range/algorithm/for_each.hpp deleted file mode 100644 index ea731b2..0000000 --- a/boost/range/algorithm/for_each.hpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) -#include -#endif - -namespace boost -{ - namespace range - { - -#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) - namespace for_each_detail - { - template - inline UnaryFunction - for_each_impl(Iterator first, Iterator last, UnaryFunction fun, - typename ::boost::enable_if< - is_reference_wrapper, - void - >::type* = 0) - { - typedef typename std::_Get_unchecked_type::type - unchecked_iterator; - - unchecked_iterator unchecked_last = std::_Unchecked(last); - for (unchecked_iterator unchecked_first = std::_Unchecked(first); first != last; ++first) - fun.get()(*unchecked_first); - - return fun; - } - - template - inline UnaryFunction - for_each_impl(Iterator first, Iterator last, UnaryFunction fn, - typename disable_if< - is_reference_wrapper, - void - >::type* = 0) - { - return std::for_each(first, last, fn); - } - } -#endif - -/// \brief template function for_each -/// -/// range-based version of the for_each std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre UnaryFunction is a model of the UnaryFunctionConcept -template< class SinglePassRange, class UnaryFunction > -inline UnaryFunction for_each(SinglePassRange & rng, UnaryFunction fun) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - -#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) - return for_each_detail::for_each_impl< - typename range_iterator::type, - UnaryFunction - >(boost::begin(rng), boost::end(rng), fun); -#else - return std::for_each< - BOOST_DEDUCED_TYPENAME range_iterator::type, - UnaryFunction - >(boost::begin(rng),boost::end(rng),fun); -#endif -} - -/// \overload -template< class SinglePassRange, class UnaryFunction > -inline UnaryFunction for_each(const SinglePassRange& rng, UnaryFunction fun) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - -#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) - return for_each_detail::for_each_impl< - typename range_iterator::type, - UnaryFunction - >(boost::begin(rng), boost::end(rng), fun); -#else - return std::for_each< - BOOST_DEDUCED_TYPENAME range_iterator::type, - UnaryFunction - >(boost::begin(rng), boost::end(rng), fun); -#endif -} - - } // namespace range - using range::for_each; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/generate.hpp b/boost/range/algorithm/generate.hpp deleted file mode 100644 index 324412c..0000000 --- a/boost/range/algorithm/generate.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_GENERATE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_GENERATE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { -/// \brief template function generate -/// -/// range-based version of the generate std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre Generator is a model of the UnaryFunctionConcept -template< class ForwardRange, class Generator > -inline ForwardRange& generate( ForwardRange& rng, Generator gen ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::generate(boost::begin(rng), boost::end(rng), gen); - return rng; -} - -/// \overload -template< class ForwardRange, class Generator > -inline const ForwardRange& generate( const ForwardRange& rng, Generator gen ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::generate(boost::begin(rng), boost::end(rng), gen); - return rng; -} - - } // namespace range - using range::generate; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/heap_algorithm.hpp b/boost/range/algorithm/heap_algorithm.hpp deleted file mode 100644 index 584920d..0000000 --- a/boost/range/algorithm/heap_algorithm.hpp +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_HEAP_ALGORITHM_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_HEAP_ALGORITHM_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function push_heap -/// -/// range-based version of the push_heap std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& push_heap(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::push_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& push_heap(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::push_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& push_heap(RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::push_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& push_heap(const RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::push_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \brief template function pop_heap -/// -/// range-based version of the pop_heap std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& pop_heap(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::pop_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& pop_heap(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::pop_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& pop_heap(RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::pop_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& pop_heap(const RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::pop_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \brief template function make_heap -/// -/// range-based version of the make_heap std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& make_heap(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::make_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& make_heap(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::make_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& make_heap(RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::make_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& make_heap(const RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::make_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \brief template function sort_heap -/// -/// range-based version of the sort_heap std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& sort_heap(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& sort_heap(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort_heap(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& sort_heap(RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& sort_heap(const RandomAccessRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort_heap(boost::begin(rng), boost::end(rng), comp_pred); - return rng; -} - - } // namespace range - using range::push_heap; - using range::pop_heap; - using range::make_heap; - using range::sort_heap; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/inplace_merge.hpp b/boost/range/algorithm/inplace_merge.hpp deleted file mode 100644 index dfadbaa..0000000 --- a/boost/range/algorithm/inplace_merge.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function inplace_merge -/// -/// range-based version of the inplace_merge std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline BidirectionalRange& inplace_merge(BidirectionalRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::inplace_merge(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - -/// \overload -template -inline const BidirectionalRange& inplace_merge(const BidirectionalRange& rng, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::inplace_merge(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - -/// \overload -template -inline BidirectionalRange& inplace_merge(BidirectionalRange& rng, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::inplace_merge(boost::begin(rng), middle, boost::end(rng), pred); - return rng; -} - -/// \overload -template -inline const BidirectionalRange& inplace_merge(const BidirectionalRange& rng, - BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::inplace_merge(boost::begin(rng), middle, boost::end(rng), pred); - return rng; -} - - } // namespace range - using range::inplace_merge; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/lexicographical_compare.hpp b/boost/range/algorithm/lexicographical_compare.hpp deleted file mode 100644 index c6e4bc8..0000000 --- a/boost/range/algorithm/lexicographical_compare.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function lexicographic_compare -/// -/// range-based version of the lexicographic_compare std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -template -inline bool lexicographical_compare(const SinglePassRange1& rng1, - const SinglePassRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::lexicographical_compare( - boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)); -} - -/// \overload -template -inline bool lexicographical_compare(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::lexicographical_compare( - boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred); -} - - } // namespace range - using range::lexicographical_compare; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/lower_bound.hpp b/boost/range/algorithm/lower_bound.hpp deleted file mode 100644 index 23dac6c..0000000 --- a/boost/range/algorithm/lower_bound.hpp +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function lower_bound -/// -/// range-based version of the lower_bound std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -lower_bound( ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::lower_bound(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -lower_bound( const ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::lower_bound(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -lower_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::lower_bound(boost::begin(rng), boost::end(rng), val, pred); -} - -/// \overload -template< class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -lower_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::lower_bound(boost::begin(rng), boost::end(rng), val, pred); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -lower_bound( ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::lower_bound(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -lower_bound( const ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::lower_bound(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -lower_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::lower_bound(boost::begin(rng), boost::end(rng), val, pred), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -lower_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::lower_bound(boost::begin(rng), boost::end(rng), val, pred), - rng); -} - - } // namespace range - using range::lower_bound; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/max_element.hpp b/boost/range/algorithm/max_element.hpp deleted file mode 100644 index 50669b3..0000000 --- a/boost/range/algorithm/max_element.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -namespace detail -{ - -template -inline Iterator -max_element(Iterator first, Iterator last, Predicate comp) -{ - if (first == last) { - return last; - } - Iterator result = first; - while (++first != last) { - if (comp(*result, *first)) { - result = first; - } - } - return result; -} - -} // namespace detail - -/// \brief template function max_element -/// -/// range-based version of the max_element std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -max_element(ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::max_element(boost::begin(rng), boost::end(rng), detail::less()); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -max_element(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::max_element(boost::begin(rng), boost::end(rng), detail::less()); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -max_element(ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::max_element(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -max_element(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::max_element(boost::begin(rng), boost::end(rng), pred); -} - -// range_return overloads - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -max_element(ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::max_element(boost::begin(rng), boost::end(rng), detail::less()), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -max_element(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::max_element(boost::begin(rng), boost::end(rng), detail::less()), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -max_element(ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::max_element(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -max_element(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::max_element(boost::begin(rng), boost::end(rng), pred), - rng); -} - - } // namespace range - using range::max_element; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/merge.hpp b/boost/range/algorithm/merge.hpp deleted file mode 100644 index c81b8c7..0000000 --- a/boost/range/algorithm/merge.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_MERGE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_MERGE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function merge -/// -/// range-based version of the merge std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -/// -template -inline OutputIterator merge(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::merge(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out); -} - -/// \overload -template -inline OutputIterator merge(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::merge(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out, pred); -} - - } // namespace range - using range::merge; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/min_element.hpp b/boost/range/algorithm/min_element.hpp deleted file mode 100644 index 764de8b..0000000 --- a/boost/range/algorithm/min_element.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -namespace detail -{ - -template -inline Iterator -min_element(Iterator first, Iterator last, Predicate comp) -{ - if (first == last) { - return last; - } - Iterator result = first; - while (++first != last) { - if (comp(*first, *result)) { - result = first; - } - } - return result; -} - -} // namespace detail - -/// \brief template function min_element -/// -/// range-based version of the min_element std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -min_element(ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::min_element(boost::begin(rng), boost::end(rng), detail::less()); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -min_element(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::min_element(boost::begin(rng), boost::end(rng), detail::less()); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -min_element(ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::min_element(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -min_element(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return detail::min_element(boost::begin(rng), boost::end(rng), pred); -} - -// range_return overloads - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -min_element(ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::min_element(boost::begin(rng), boost::end(rng), detail::less()), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -min_element(const ForwardRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::min_element(boost::begin(rng), boost::end(rng), detail::less()), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -min_element(ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::min_element(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -min_element(const ForwardRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - detail::min_element(boost::begin(rng), boost::end(rng), pred), - rng); -} - - } // namespace range - using range::min_element; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/mismatch.hpp b/boost/range/algorithm/mismatch.hpp deleted file mode 100644 index 2819c33..0000000 --- a/boost/range/algorithm/mismatch.hpp +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_MISMATCH_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_MISMATCH_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range_detail - { - template< class SinglePassTraversalReadableIterator1, - class SinglePassTraversalReadableIterator2 > - inline std::pair - mismatch_impl(SinglePassTraversalReadableIterator1 first1, - SinglePassTraversalReadableIterator1 last1, - SinglePassTraversalReadableIterator2 first2, - SinglePassTraversalReadableIterator2 last2) - { - while (first1 != last1 && first2 != last2 && *first1 == *first2) - { - ++first1; - ++first2; - } - return std::pair(first1, first2); - } - - template< class SinglePassTraversalReadableIterator1, - class SinglePassTraversalReadableIterator2, - class BinaryPredicate > - inline std::pair - mismatch_impl(SinglePassTraversalReadableIterator1 first1, - SinglePassTraversalReadableIterator1 last1, - SinglePassTraversalReadableIterator2 first2, - SinglePassTraversalReadableIterator2 last2, - BinaryPredicate pred) - { - while (first1 != last1 && first2 != last2 && pred(*first1, *first2)) - { - ++first1; - ++first2; - } - return std::pair(first1, first2); - } - } // namespace range_detail - - namespace range - { -/// \brief template function mismatch -/// -/// range-based version of the mismatch std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< class SinglePassRange1, class SinglePassRange2 > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(SinglePassRange1& rng1, const SinglePassRange2 & rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2)); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2)); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(SinglePassRange1& rng1, SinglePassRange2 & rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2)); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2)); -} - - -/// \overload -template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(SinglePassRange1& rng1, const SinglePassRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), pred); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), pred); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(SinglePassRange1& rng1, SinglePassRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), pred); -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > -inline std::pair< - BOOST_DEDUCED_TYPENAME range_iterator::type, - BOOST_DEDUCED_TYPENAME range_iterator::type > -mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::mismatch_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), pred); -} - - } // namespace range - using range::mismatch; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/nth_element.hpp b/boost/range/algorithm/nth_element.hpp deleted file mode 100644 index a605595..0000000 --- a/boost/range/algorithm/nth_element.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function nth_element -/// -/// range-based version of the nth_element std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& nth_element(RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type nth) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::nth_element(boost::begin(rng), nth, boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& nth_element(const RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type nth) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::nth_element(boost::begin(rng), nth, boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& nth_element(RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type nth, - BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::nth_element(boost::begin(rng), nth, boost::end(rng), sort_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& nth_element(const RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type nth, - BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::nth_element(boost::begin(rng), nth, boost::end(rng), sort_pred); - return rng; -} - - } // namespace range - using range::nth_element; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/partial_sort.hpp b/boost/range/algorithm/partial_sort.hpp deleted file mode 100644 index d7044cd..0000000 --- a/boost/range/algorithm/partial_sort.hpp +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function partial_sort -/// -/// range-based version of the partial_sort std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& partial_sort(RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::partial_sort(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& partial_sort(const RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::partial_sort(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& partial_sort(RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle, - BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::partial_sort(boost::begin(rng), middle, boost::end(rng), - sort_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& partial_sort(const RandomAccessRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle, - BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::partial_sort(boost::begin(rng), middle, boost::end(rng), - sort_pred); - return rng; -} - - } // namespace range - using range::partial_sort; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/partial_sort_copy.hpp b/boost/range/algorithm/partial_sort_copy.hpp deleted file mode 100644 index 9129389..0000000 --- a/boost/range/algorithm/partial_sort_copy.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function partial_sort_copy -/// -/// range-based version of the partial_sort_copy std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre RandomAccessRange is a model of the Mutable_RandomAccessRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partial_sort_copy(const SinglePassRange& rng1, RandomAccessRange& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partial_sort_copy(const SinglePassRange& rng1, const RandomAccessRange& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partial_sort_copy(const SinglePassRange& rng1, RandomAccessRange& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partial_sort_copy(const SinglePassRange& rng1, const RandomAccessRange& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred); -} - - } // namespace range - using range::partial_sort_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/partition.hpp b/boost/range/algorithm/partition.hpp deleted file mode 100644 index b814a24..0000000 --- a/boost/range/algorithm/partition.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_PARTITION__HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_PARTITION__HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function partition -/// -/// range-based version of the partition std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partition(ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::partition(boost::begin(rng),boost::end(rng),pred); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -partition(const ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::partition(boost::begin(rng),boost::end(rng),pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class ForwardRange, - class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -partition(ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return boost::range_return:: - pack(std::partition(boost::begin(rng), boost::end(rng), pred), rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, - class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -partition(const ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return boost::range_return:: - pack(std::partition(boost::begin(rng), boost::end(rng), pred), rng); -} - - } // namespace range - using range::partition; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/permutation.hpp b/boost/range/algorithm/permutation.hpp deleted file mode 100644 index 75388cc..0000000 --- a/boost/range/algorithm/permutation.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_PERMUTATION_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_PERMUTATION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function next_permutation -/// -/// range-based version of the next_permutation std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline bool next_permutation(BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::next_permutation(boost::begin(rng), boost::end(rng)); -} - -/// \overload -template -inline bool next_permutation(const BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::next_permutation(boost::begin(rng), boost::end(rng)); -} - -/// \overload -template -inline bool next_permutation(BidirectionalRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::next_permutation(boost::begin(rng), boost::end(rng), - comp_pred); -} - -/// \overload -template -inline bool next_permutation(const BidirectionalRange& rng, - Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::next_permutation(boost::begin(rng), boost::end(rng), - comp_pred); -} - -/// \brief template function prev_permutation -/// -/// range-based version of the prev_permutation std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -/// \pre Compare is a model of the BinaryPredicateConcept -template -inline bool prev_permutation(BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::prev_permutation(boost::begin(rng), boost::end(rng)); -} - -/// \overload -template -inline bool prev_permutation(const BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::prev_permutation(boost::begin(rng), boost::end(rng)); -} - -/// \overload -template -inline bool prev_permutation(BidirectionalRange& rng, Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::prev_permutation(boost::begin(rng), boost::end(rng), - comp_pred); -} - -/// \overload -template -inline bool prev_permutation(const BidirectionalRange& rng, - Compare comp_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::prev_permutation(boost::begin(rng), boost::end(rng), - comp_pred); -} - - } // namespace range - using range::next_permutation; - using range::prev_permutation; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/random_shuffle.hpp b/boost/range/algorithm/random_shuffle.hpp deleted file mode 100644 index 33e98e0..0000000 --- a/boost/range/algorithm/random_shuffle.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE -#include -#endif - -namespace boost -{ - namespace range - { - - namespace detail - { -#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE - -// wrap std::rand as UniformRandomBitGenerator -struct wrap_rand -{ - typedef unsigned int result_type; - - static BOOST_CONSTEXPR result_type (min)() - { - return 0; - } - - static BOOST_CONSTEXPR result_type (max)() - { - return RAND_MAX; - } - - result_type operator()() - { - return std::rand(); - } -}; - -template< class RandomIt > -inline void random_shuffle(RandomIt first, RandomIt last) -{ - std::shuffle(first, last, wrap_rand()); -} - -// wrap Generator as UniformRandomBitGenerator -template< class Generator > -struct wrap_generator -{ - typedef unsigned int result_type; - static const int max_arg = ((0u - 1u) >> 2) + 1; - Generator& g; - - wrap_generator(Generator& gen) : g(gen) {} - - static BOOST_CONSTEXPR result_type (min)() - { - return 0; - } - - static BOOST_CONSTEXPR result_type (max)() - { - return max_arg - 1; - } - - result_type operator()() - { - return static_cast(g(max_arg)); - } -}; - -template< class RandomIt, class Generator > -inline void random_shuffle(RandomIt first, RandomIt last, Generator& gen) -{ - std::shuffle(first, last, wrap_generator< Generator >(gen)); -} - -#else - -using std::random_shuffle; - -#endif - } // namespace detail - -/// \brief template function random_shuffle -/// -/// range-based version of the random_shuffle std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre Generator is a model of the UnaryFunctionConcept -template -inline RandomAccessRange& random_shuffle(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - detail::random_shuffle(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - detail::random_shuffle(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& random_shuffle(RandomAccessRange& rng, Generator& gen) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng, Generator& gen) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); - return rng; -} - - } // namespace range - using range::random_shuffle; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/remove.hpp b/boost/range/algorithm/remove.hpp deleted file mode 100644 index 699a7cd..0000000 --- a/boost/range/algorithm/remove.hpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function remove -/// -/// range-based version of the remove std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -remove(ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::remove(boost::begin(rng),boost::end(rng),val); -} - -/// \overload -template< class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -remove(const ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::remove(boost::begin(rng),boost::end(rng),val); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -remove(ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - std::remove(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -remove(const ForwardRange& rng, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - std::remove(boost::begin(rng), boost::end(rng), val), - rng); -} - - } // namespace range - using range::remove; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/remove_copy.hpp b/boost/range/algorithm/remove_copy.hpp deleted file mode 100644 index b65747e..0000000 --- a/boost/range/algorithm/remove_copy.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function remove_copy -/// -/// range-based version of the remove_copy std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre OutputIterator is a model of the OutputIteratorConcept -/// \pre Value is a model of the EqualityComparableConcept -/// \pre Objects of type Value can be compared for equality with objects of -/// InputIterator's value type. -template< class SinglePassRange, class OutputIterator, class Value > -inline OutputIterator -remove_copy(const SinglePassRange& rng, OutputIterator out_it, const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::remove_copy(boost::begin(rng), boost::end(rng), out_it, val); -} - - } // namespace range - using range::remove_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/remove_copy_if.hpp b/boost/range/algorithm/remove_copy_if.hpp deleted file mode 100644 index 8d9c37b..0000000 --- a/boost/range/algorithm/remove_copy_if.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - /// \brief template function remove_copy_if - /// - /// range-based version of the remove_copy_if std algorithm - /// - /// \pre SinglePassRange is a model of the SinglePassRangeConcept - /// \pre OutputIterator is a model of the OutputIteratorConcept - /// \pre Predicate is a model of the PredicateConcept - /// \pre InputIterator's value type is convertible to Predicate's argument type - /// \pre out_it is not an iterator in the range rng - template< class SinglePassRange, class OutputIterator, class Predicate > - inline OutputIterator - remove_copy_if(const SinglePassRange& rng, OutputIterator out_it, Predicate pred) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::remove_copy_if(boost::begin(rng), boost::end(rng), out_it, pred); - } -} - -#endif // include guard diff --git a/boost/range/algorithm/remove_if.hpp b/boost/range/algorithm/remove_if.hpp deleted file mode 100644 index a965df0..0000000 --- a/boost/range/algorithm/remove_if.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function remove_if -/// -/// range-based version of the remove_if std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre UnaryPredicate is a model of the UnaryPredicateConcept -template< class ForwardRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type -remove_if(ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::remove_if(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template< class ForwardRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type -remove_if(const ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::remove_if(boost::begin(rng), boost::end(rng), pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class ForwardRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -remove_if(ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - std::remove_if(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class UnaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -remove_if(const ForwardRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return::pack( - std::remove_if(boost::begin(rng), boost::end(rng), pred), - rng); -} - - } // namespace range - using range::remove_if; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/replace.hpp b/boost/range/algorithm/replace.hpp deleted file mode 100644 index 44d3e4c..0000000 --- a/boost/range/algorithm/replace.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REPLACE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REPLACE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function replace -/// -/// range-based version of the replace std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class Value > -inline ForwardRange& -replace(ForwardRange& rng, const Value& what, - const Value& with_what) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::replace(boost::begin(rng), boost::end(rng), what, with_what); - return rng; -} - -/// \overload -template< class ForwardRange, class Value > -inline const ForwardRange& -replace(const ForwardRange& rng, const Value& what, - const Value& with_what) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::replace(boost::begin(rng), boost::end(rng), what, with_what); - return rng; -} - - } // namespace range - using range::replace; -} // namespace boost; - -#endif // include guard diff --git a/boost/range/algorithm/replace_copy.hpp b/boost/range/algorithm/replace_copy.hpp deleted file mode 100644 index 0c02005..0000000 --- a/boost/range/algorithm/replace_copy.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function replace_copy -/// -/// range-based version of the replace_copy std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class OutputIterator, class Value > -inline OutputIterator -replace_copy(const ForwardRange& rng, OutputIterator out_it, const Value& what, - const Value& with_what) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::replace_copy(boost::begin(rng), boost::end(rng), out_it, - what, with_what); -} - - } // namespace range - using range::replace_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/replace_copy_if.hpp b/boost/range/algorithm/replace_copy_if.hpp deleted file mode 100644 index d313151..0000000 --- a/boost/range/algorithm/replace_copy_if.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function replace_copy_if -/// -/// range-based version of the replace_copy_if std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre Predicate is a model of the PredicateConcept -/// \pre Value is convertible to Predicate's argument type -/// \pre Value is Assignable -/// \pre Value is convertible to a type in OutputIterator's set of value types. -template< class ForwardRange, class OutputIterator, class Predicate, class Value > -inline OutputIterator -replace_copy_if(const ForwardRange& rng, OutputIterator out_it, Predicate pred, - const Value& with_what) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::replace_copy_if(boost::begin(rng), boost::end(rng), out_it, - pred, with_what); -} - - } // namespace range - using range::replace_copy_if; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/replace_if.hpp b/boost/range/algorithm/replace_if.hpp deleted file mode 100644 index 93d5a1f..0000000 --- a/boost/range/algorithm/replace_if.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function replace_if -/// -/// range-based version of the replace_if std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre UnaryPredicate is a model of the UnaryPredicateConcept -template< class ForwardRange, class UnaryPredicate, class Value > -inline ForwardRange& - replace_if(ForwardRange& rng, UnaryPredicate pred, - const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::replace_if(boost::begin(rng), boost::end(rng), pred, val); - return rng; -} - -/// \overload -template< class ForwardRange, class UnaryPredicate, class Value > -inline const ForwardRange& - replace_if(const ForwardRange& rng, UnaryPredicate pred, - const Value& val) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::replace_if(boost::begin(rng), boost::end(rng), pred, val); - return rng; -} - - } // namespace range - using range::replace_if; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/reverse.hpp b/boost/range/algorithm/reverse.hpp deleted file mode 100644 index 20a7eb1..0000000 --- a/boost/range/algorithm/reverse.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REVERSE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REVERSE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function reverse -/// -/// range-based version of the reverse std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -template -inline BidirectionalRange& reverse(BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::reverse(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const BidirectionalRange& reverse(const BidirectionalRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - std::reverse(boost::begin(rng), boost::end(rng)); - return rng; -} - - } // namespace range - using range::reverse; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/reverse_copy.hpp b/boost/range/algorithm/reverse_copy.hpp deleted file mode 100644 index f1990ad..0000000 --- a/boost/range/algorithm/reverse_copy.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function reverse_copy -/// -/// range-based version of the reverse_copy std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -template -inline OutputIterator reverse_copy(const BidirectionalRange& rng, OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::reverse_copy(boost::begin(rng), boost::end(rng), out); -} - - } // namespace range - using range::reverse_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/rotate.hpp b/boost/range/algorithm/rotate.hpp deleted file mode 100644 index ca4b223..0000000 --- a/boost/range/algorithm/rotate.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_ROTATE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_ROTATE_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function rotate -/// -/// range-based version of the rotate std algorithm -/// -/// \pre Rng meets the requirements for a Forward range -template -inline ForwardRange& rotate(ForwardRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::rotate(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - -/// \overload -template -inline const ForwardRange& rotate(const ForwardRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - std::rotate(boost::begin(rng), middle, boost::end(rng)); - return rng; -} - - } // namespace range - using range::rotate; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/rotate_copy.hpp b/boost/range/algorithm/rotate_copy.hpp deleted file mode 100644 index 0409ac5..0000000 --- a/boost/range/algorithm/rotate_copy.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - - /// \brief template function rotate - /// - /// range-based version of the rotate std algorithm - /// - /// \pre Rng meets the requirements for a Forward range - template - inline OutputIterator rotate_copy( - const ForwardRange& rng, - BOOST_DEDUCED_TYPENAME range_iterator::type middle, - OutputIterator target - ) - { - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::rotate_copy(boost::begin(rng), middle, boost::end(rng), target); - } - - } // namespace range - using range::rotate_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/search.hpp b/boost/range/algorithm/search.hpp deleted file mode 100644 index 28cc6e6..0000000 --- a/boost/range/algorithm/search.hpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_SEARCH_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_SEARCH_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function search -/// -/// range-based version of the search std algorithm -/// -/// \pre ForwardRange1 is a model of the ForwardRangeConcept -/// \pre ForwardRange2 is a model of the ForwardRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search(ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search(const ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::search(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2)); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred); -} - -/// \overload -template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::search(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_return::type -search(ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2 > -inline BOOST_DEDUCED_TYPENAME range_return::type -search(const ForwardRange1& rng1, const ForwardRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred), - rng1); -} - -/// \overload -template< range_return_value re, class ForwardRange1, class ForwardRange2, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -search(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::search(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2),pred), - rng1); -} - - } // namespace range - using range::search; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/search_n.hpp b/boost/range/algorithm/search_n.hpp deleted file mode 100644 index ccfb27a..0000000 --- a/boost/range/algorithm/search_n.hpp +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - -namespace range_detail -{ - // Rationale: search_n is implemented rather than delegate to - // the standard library implementation because some standard - // library implementations are broken eg. MSVC. - - // search_n forward iterator version - template - inline ForwardIterator - search_n_impl(ForwardIterator first, ForwardIterator last, Integer count, - const Value& value, std::forward_iterator_tag) - { - first = std::find(first, last, value); - while (first != last) - { - typename std::iterator_traits::difference_type n = count; - ForwardIterator i = first; - ++i; - while (i != last && n != 1 && *i==value) - { - ++i; - --n; - } - if (n == 1) - return first; - if (i == last) - return last; - first = std::find(++i, last, value); - } - return last; - } - - // search_n random-access iterator version - template - inline RandomAccessIterator - search_n_impl(RandomAccessIterator first, RandomAccessIterator last, - Integer count, const Value& value, - std::random_access_iterator_tag) - { - typedef typename std::iterator_traits::difference_type difference_t; - - difference_t tail_size = last - first; - const difference_t pattern_size = count; - - if (tail_size < pattern_size) - return last; - - const difference_t skip_offset = pattern_size - 1; - RandomAccessIterator look_ahead = first + skip_offset; - tail_size -= pattern_size; - - while (1) - { - // look_ahead here is pointing to the last element of the - // next possible match - while (!(*look_ahead == value)) // skip loop... - { - if (tail_size < pattern_size) - return last; // no match - look_ahead += pattern_size; - tail_size -= pattern_size; - } - difference_t remainder = skip_offset; - for (RandomAccessIterator back_track = look_ahead - 1; - *back_track == value; --back_track) - { - if (--remainder == 0) - { - return look_ahead - skip_offset; // matched - } - } - if (remainder > tail_size) - return last; // no match - look_ahead += remainder; - tail_size -= remainder; - } - - return last; - } - - // search_n for forward iterators using a binary predicate - // to determine a match - template - inline ForwardIterator - search_n_pred_impl(ForwardIterator first, ForwardIterator last, - Integer count, const Value& value, - BinaryPredicate pred, std::forward_iterator_tag) - { - typedef typename std::iterator_traits::difference_type difference_t; - - while (first != last && !static_cast(pred(*first, value))) - ++first; - - while (first != last) - { - difference_t n = count; - ForwardIterator i = first; - ++i; - while (i != last && n != 1 && static_cast(pred(*i, value))) - { - ++i; - --n; - } - if (n == 1) - return first; - if (i == last) - return last; - first = ++i; - while (first != last && !static_cast(pred(*first, value))) - ++first; - } - return last; - } - - // search_n for random-access iterators using a binary predicate - // to determine a match - template - inline RandomAccessIterator - search_n_pred_impl(RandomAccessIterator first, RandomAccessIterator last, - Integer count, const Value& value, - BinaryPredicate pred, std::random_access_iterator_tag) - { - typedef typename std::iterator_traits::difference_type difference_t; - - difference_t tail_size = last - first; - const difference_t pattern_size = count; - - if (tail_size < pattern_size) - return last; - - const difference_t skip_offset = pattern_size - 1; - RandomAccessIterator look_ahead = first + skip_offset; - tail_size -= pattern_size; - - while (1) - { - // look_ahead points to the last element of the next - // possible match - while (!static_cast(pred(*look_ahead, value))) // skip loop - { - if (tail_size < pattern_size) - return last; // no match - look_ahead += pattern_size; - tail_size -= pattern_size; - } - difference_t remainder = skip_offset; - for (RandomAccessIterator back_track = look_ahead - 1; - pred(*back_track, value); --back_track) - { - if (--remainder == 0) - return look_ahead -= skip_offset; // success - } - if (remainder > tail_size) - { - return last; // no match - } - look_ahead += remainder; - tail_size -= remainder; - } - } - - template - inline ForwardIterator - search_n_impl(ForwardIterator first, ForwardIterator last, - Integer count, const Value& value) - { - BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); - BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept)); - BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept::value_type>)); - //BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2::value_type, Value>)); - - typedef typename std::iterator_traits::iterator_category cat_t; - - if (count <= 0) - return first; - if (count == 1) - return std::find(first, last, value); - return range_detail::search_n_impl(first, last, count, value, cat_t()); - } - - template - inline ForwardIterator - search_n_pred_impl(ForwardIterator first, ForwardIterator last, - Integer count, const Value& value, - BinaryPredicate pred) - { - BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); - BOOST_RANGE_CONCEPT_ASSERT(( - BinaryPredicateConcept< - BinaryPredicate, - typename std::iterator_traits::value_type, - Value> - )); - - typedef typename std::iterator_traits::iterator_category cat_t; - - if (count <= 0) - return first; - if (count == 1) - { - while (first != last && !static_cast(pred(*first, value))) - ++first; - return first; - } - return range_detail::search_n_pred_impl(first, last, count, - value, pred, cat_t()); - } -} // namespace range_detail - -namespace range { - -/// \brief template function search -/// -/// range-based version of the search std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -/// \pre Integer is an integral type -/// \pre Value is a model of the EqualityComparableConcept -/// \pre ForwardRange's value type is a model of the EqualityComparableConcept -/// \pre Object's of ForwardRange's value type can be compared for equality with Objects of type Value -template< class ForwardRange, class Integer, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search_n(ForwardRange& rng, Integer count, const Value& value) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value); -} - -/// \overload -template< class ForwardRange, class Integer, class Value > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search_n(const ForwardRange& rng, Integer count, const Value& value) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value); -} - -/// \overload -template< class ForwardRange, class Integer, class Value, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search_n(ForwardRange& rng, Integer count, const Value& value, - BinaryPredicate binary_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); - return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng), - count, value, binary_pred); -} - -/// \overload -template< class ForwardRange, class Integer, class Value, - class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -search_n(const ForwardRange& rng, Integer count, const Value& value, - BinaryPredicate binary_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); - return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng), - count, value, binary_pred); -} - -// range_return overloads - -/// \overload -template< range_return_value re, class ForwardRange, class Integer, - class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -search_n(ForwardRange& rng, Integer count, const Value& value) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_return:: - pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng), - count, value), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Integer, - class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -search_n(const ForwardRange& rng, Integer count, const Value& value) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - return range_return:: - pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng), - count, value), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Integer, - class Value, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -search_n(ForwardRange& rng, Integer count, const Value& value, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - const Value&>)); - return range_return:: - pack(range_detail::search_n_pred_impl(boost::begin(rng), - boost::end(rng), - count, value, pred), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Integer, - class Value, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -search_n(const ForwardRange& rng, Integer count, const Value& value, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - const Value&>)); - return range_return:: - pack(range_detail::search_n_pred_impl(boost::begin(rng), - boost::end(rng), - count, value, pred), - rng); -} - - } // namespace range - using range::search_n; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/set_algorithm.hpp b/boost/range/algorithm/set_algorithm.hpp deleted file mode 100644 index 82ef8ec..0000000 --- a/boost/range/algorithm/set_algorithm.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_SET_ALGORITHM_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_SET_ALGORITHM_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function includes -/// -/// range-based version of the includes std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline bool includes(const SinglePassRange1& rng1, - const SinglePassRange2& rng2) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::includes(boost::begin(rng1),boost::end(rng1), - boost::begin(rng2),boost::end(rng2)); -} - -/// \overload -template -inline bool includes(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::includes(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), pred); -} - -/// \brief template function set_union -/// -/// range-based version of the set_union std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline OutputIterator set_union(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_union(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out); -} - -/// \overload -template -inline OutputIterator set_union(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_union(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out, pred); -} - -/// \brief template function set_intersection -/// -/// range-based version of the set_intersection std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline OutputIterator set_intersection(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_intersection(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out); -} - -/// \overload -template -inline OutputIterator set_intersection(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_intersection(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), - out, pred); -} - -/// \brief template function set_difference -/// -/// range-based version of the set_difference std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline OutputIterator set_difference(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_difference(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out); -} - -/// \overload -template -inline OutputIterator set_difference(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_difference( - boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out, pred); -} - -/// \brief template function set_symmetric_difference -/// -/// range-based version of the set_symmetric_difference std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline OutputIterator -set_symmetric_difference(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_symmetric_difference(boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out); -} - -/// \overload -template -inline OutputIterator -set_symmetric_difference(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::set_symmetric_difference( - boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), out, pred); -} - - } // namespace range - using range::includes; - using range::set_union; - using range::set_intersection; - using range::set_difference; - using range::set_symmetric_difference; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/sort.hpp b/boost/range/algorithm/sort.hpp deleted file mode 100644 index 45eecde..0000000 --- a/boost/range/algorithm/sort.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_SORT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_SORT_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function sort -/// -/// range-based version of the sort std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& sort(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& sort(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& sort(RandomAccessRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort(boost::begin(rng), boost::end(rng), pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& sort(const RandomAccessRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::sort(boost::begin(rng), boost::end(rng), pred); - return rng; -} - - } // namespace range - using range::sort; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/stable_partition.hpp b/boost/range/algorithm/stable_partition.hpp deleted file mode 100644 index 24febfc..0000000 --- a/boost/range/algorithm/stable_partition.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function stable_partition -/// -/// range-based version of the stable_partition std algorithm -/// -/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept -/// \pre UnaryPredicate is a model of the UnaryPredicateConcept -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -stable_partition(BidirectionalRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::stable_partition(boost::begin(rng), boost::end(rng), pred); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_iterator::type -stable_partition(const BidirectionalRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return std::stable_partition(boost::begin(rng),boost::end(rng),pred); -} - -// range_return overloads -template -inline BOOST_DEDUCED_TYPENAME range_return::type -stable_partition(BidirectionalRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return range_return::pack( - std::stable_partition(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template -inline BOOST_DEDUCED_TYPENAME range_return::type -stable_partition(const BidirectionalRange& rng, UnaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); - return range_return::pack( - std::stable_partition(boost::begin(rng),boost::end(rng),pred), - rng); -} - - } // namespace range - using range::stable_partition; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/stable_sort.hpp b/boost/range/algorithm/stable_sort.hpp deleted file mode 100644 index d18da4d..0000000 --- a/boost/range/algorithm/stable_sort.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function stable_sort -/// -/// range-based version of the stable_sort std algorithm -/// -/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template -inline RandomAccessRange& stable_sort(RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::stable_sort(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& stable_sort(const RandomAccessRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::stable_sort(boost::begin(rng), boost::end(rng)); - return rng; -} - -/// \overload -template -inline RandomAccessRange& stable_sort(RandomAccessRange& rng, BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::stable_sort(boost::begin(rng), boost::end(rng), sort_pred); - return rng; -} - -/// \overload -template -inline const RandomAccessRange& stable_sort(const RandomAccessRange& rng, BinaryPredicate sort_pred) -{ - BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); - std::stable_sort(boost::begin(rng), boost::end(rng), sort_pred); - return rng; -} - - } // namespace range - using range::stable_sort; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/swap_ranges.hpp b/boost/range/algorithm/swap_ranges.hpp deleted file mode 100644 index 52b0162..0000000 --- a/boost/range/algorithm/swap_ranges.hpp +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range_detail - { - template - void swap_ranges_impl(Iterator1 it1, Iterator1 last1, - Iterator2 it2, Iterator2 last2, - single_pass_traversal_tag, - single_pass_traversal_tag) - { - ignore_unused_variable_warning(last2); - for (; it1 != last1; ++it1, ++it2) - { - BOOST_ASSERT( it2 != last2 ); - std::iter_swap(it1, it2); - } - } - - template - void swap_ranges_impl(Iterator1 it1, Iterator1 last1, - Iterator2 it2, Iterator2 last2, - random_access_traversal_tag, - random_access_traversal_tag) - { - ignore_unused_variable_warning(last2); - BOOST_ASSERT( last2 - it2 >= last1 - it1 ); - std::swap_ranges(it1, last1, it2); - } - - template - void swap_ranges_impl(Iterator1 first1, Iterator1 last1, - Iterator2 first2, Iterator2 last2) - { - swap_ranges_impl(first1, last1, first2, last2, - BOOST_DEDUCED_TYPENAME iterator_traversal::type(), - BOOST_DEDUCED_TYPENAME iterator_traversal::type()); - } - } // namespace range_detail - - namespace range - { - -/// \brief template function swap_ranges -/// -/// range-based version of the swap_ranges std algorithm -/// -/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept -/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept -template< class SinglePassRange1, class SinglePassRange2 > -inline SinglePassRange2& -swap_ranges(SinglePassRange1& range1, SinglePassRange2& range2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - boost::range_detail::swap_ranges_impl( - boost::begin(range1), boost::end(range1), - boost::begin(range2), boost::end(range2)); - - return range2; -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline SinglePassRange2& -swap_ranges(const SinglePassRange1& range1, SinglePassRange2& range2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - boost::range_detail::swap_ranges_impl( - boost::begin(range1), boost::end(range1), - boost::begin(range2), boost::end(range2)); - - return range2; -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline const SinglePassRange2& -swap_ranges(SinglePassRange1& range1, const SinglePassRange2& range2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - boost::range_detail::swap_ranges_impl( - boost::begin(range1), boost::end(range1), - boost::begin(range2), boost::end(range2)); - - return range2; -} - -/// \overload -template< class SinglePassRange1, class SinglePassRange2 > -inline const SinglePassRange2& -swap_ranges(const SinglePassRange1& range1, const SinglePassRange2& range2) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - - boost::range_detail::swap_ranges_impl( - boost::begin(range1), boost::end(range1), - boost::begin(range2), boost::end(range2)); - - return range2; -} - - } // namespace range - using range::swap_ranges; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/transform.hpp b/boost/range/algorithm/transform.hpp deleted file mode 100644 index ade147a..0000000 --- a/boost/range/algorithm/transform.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - - /// \brief template function transform - /// - /// range-based version of the transform std algorithm - /// - /// \pre SinglePassRange1 is a model of the SinglePassRangeConcept - /// \pre SinglePassRange2 is a model of the SinglePassRangeConcept - /// \pre OutputIterator is a model of the OutputIteratorConcept - /// \pre UnaryOperation is a model of the UnaryFunctionConcept - /// \pre BinaryOperation is a model of the BinaryFunctionConcept - template< class SinglePassRange1, - class OutputIterator, - class UnaryOperation > - inline OutputIterator - transform(const SinglePassRange1& rng, - OutputIterator out, - UnaryOperation fun) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::transform(boost::begin(rng),boost::end(rng),out,fun); - } - - } // namespace range - - namespace range_detail - { - template< class SinglePassTraversalReadableIterator1, - class SinglePassTraversalReadableIterator2, - class OutputIterator, - class BinaryFunction > - inline OutputIterator - transform_impl(SinglePassTraversalReadableIterator1 first1, - SinglePassTraversalReadableIterator1 last1, - SinglePassTraversalReadableIterator2 first2, - SinglePassTraversalReadableIterator2 last2, - OutputIterator out, - BinaryFunction fn) - { - for (; first1 != last1 && first2 != last2; ++first1, ++first2) - { - *out = fn(*first1, *first2); - ++out; - } - return out; - } - } - - namespace range - { - - /// \overload - template< class SinglePassRange1, - class SinglePassRange2, - class OutputIterator, - class BinaryOperation > - inline OutputIterator - transform(const SinglePassRange1& rng1, - const SinglePassRange2& rng2, - OutputIterator out, - BinaryOperation fun) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return boost::range_detail::transform_impl( - boost::begin(rng1), boost::end(rng1), - boost::begin(rng2), boost::end(rng2), - out, fun); - } - - } // namespace range - using range::transform; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/unique.hpp b/boost/range/algorithm/unique.hpp deleted file mode 100644 index 8017a83..0000000 --- a/boost/range/algorithm/unique.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_UNIQUE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_UNIQUE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function unique -/// -/// range-based version of the unique std algorithm -/// -/// \pre Rng meets the requirements for a Forward range -template< range_return_value re, class ForwardRange > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( ForwardRange& rng ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack( std::unique( boost::begin(rng), - boost::end(rng)), rng ); -} - -/// \overload -template< range_return_value re, class ForwardRange > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( const ForwardRange& rng ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack( std::unique( boost::begin(rng), - boost::end(rng)), rng ); -} -/// \overload -template< range_return_value re, class ForwardRange, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( ForwardRange& rng, BinaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::unique(boost::begin(rng), boost::end(rng), pred), - rng); -} -/// \overload -template< range_return_value re, class ForwardRange, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( const ForwardRange& rng, BinaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::unique(boost::begin(rng), boost::end(rng), pred), - rng); -} - -/// \overload -template< class ForwardRange > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( ForwardRange& rng ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return ::boost::range::unique(rng); -} -/// \overload -template< class ForwardRange > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( const ForwardRange& rng ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return ::boost::range::unique(rng); -} -/// \overload -template< class ForwardRange, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( ForwardRange& rng, BinaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return ::boost::range::unique(rng, pred); -} -/// \overload -template< class ForwardRange, class BinaryPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -unique( const ForwardRange& rng, BinaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return ::boost::range::unique(rng, pred); -} - - } // namespace range - using range::unique; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/unique_copy.hpp b/boost/range/algorithm/unique_copy.hpp deleted file mode 100644 index 0682d74..0000000 --- a/boost/range/algorithm/unique_copy.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function unique_copy -/// -/// range-based version of the unique_copy std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre OutputIterator is a model of the OutputIteratorConcept -/// \pre BinaryPredicate is a model of the BinaryPredicateConcept -template< class SinglePassRange, class OutputIterator > -inline OutputIterator -unique_copy( const SinglePassRange& rng, OutputIterator out_it ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::unique_copy(boost::begin(rng), boost::end(rng), out_it); -} -/// \overload -template< class SinglePassRange, class OutputIterator, class BinaryPredicate > -inline OutputIterator -unique_copy( const SinglePassRange& rng, OutputIterator out_it, - BinaryPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - return std::unique_copy(boost::begin(rng), boost::end(rng), out_it, pred); -} - - } // namespace range - using range::unique_copy; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm/upper_bound.hpp b/boost/range/algorithm/upper_bound.hpp deleted file mode 100644 index 9abf4b3..0000000 --- a/boost/range/algorithm/upper_bound.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function upper_bound -/// -/// range-based version of the upper_bound std algorithm -/// -/// \pre ForwardRange is a model of the ForwardRangeConcept -template< class ForwardRange, class Value > -inline -BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -upper_bound( ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::upper_bound(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class ForwardRange, class Value > -BOOST_DEDUCED_TYPENAME range_iterator::type -upper_bound( const ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::upper_bound(boost::begin(rng), boost::end(rng), val); -} - -/// \overload -template< class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_iterator::type ->::type -upper_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::upper_bound(boost::begin(rng), boost::end(rng), val, pred); -} - -/// \overload -template< class ForwardRange, class Value, class SortPredicate > -inline BOOST_DEDUCED_TYPENAME range_iterator::type -upper_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return std::upper_bound(boost::begin(rng), boost::end(rng), val, pred); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -upper_bound( ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::upper_bound(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value > -inline BOOST_DEDUCED_TYPENAME range_return::type -upper_bound( const ForwardRange& rng, const Value& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::upper_bound(boost::begin(rng), boost::end(rng), val), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value, - class SortPredicate > -inline BOOST_DEDUCED_TYPENAME disable_if< - is_const, - BOOST_DEDUCED_TYPENAME range_return::type ->::type -upper_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::upper_bound(boost::begin(rng), boost::end(rng), val, pred), - rng); -} - -/// \overload -template< range_return_value re, class ForwardRange, class Value, - class SortPredicate > -inline BOOST_DEDUCED_TYPENAME range_return::type -upper_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - return range_return:: - pack(std::upper_bound(boost::begin(rng), boost::end(rng), val, pred), - rng); -} - - } // namespace range - using range::upper_bound; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/copy_n.hpp b/boost/range/algorithm_ext/copy_n.hpp deleted file mode 100644 index f855441..0000000 --- a/boost/range/algorithm_ext/copy_n.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_COPY_N_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_COPY_N_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function copy -/// -/// range-based version of the copy std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -/// \pre OutputIterator is a model of the OutputIteratorConcept -/// \pre 0 <= n <= distance(rng) -template< class SinglePassRange, class Size, class OutputIterator > -inline OutputIterator copy_n(const SinglePassRange& rng, Size n, OutputIterator out) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_ASSERT( n <= static_cast(::boost::distance(rng)) ); - BOOST_ASSERT( n >= static_cast(0) ); - - BOOST_DEDUCED_TYPENAME range_iterator::type source = ::boost::begin(rng); - - for (Size i = 0; i < n; ++i, ++out, ++source) - *out = *source; - - return out; -} - - } // namespace range - using ::boost::range::copy_n; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/erase.hpp b/boost/range/algorithm_ext/erase.hpp deleted file mode 100644 index 1b47f9b..0000000 --- a/boost/range/algorithm_ext/erase.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_ERASE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_ERASE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class Container > -inline Container& erase( Container& on, - iterator_range to_erase ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - on.erase( boost::begin(to_erase), boost::end(to_erase) ); - return on; -} - -template< class Container, class T > -inline Container& remove_erase( Container& on, const T& val ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - on.erase( - std::remove(boost::begin(on), boost::end(on), val), - boost::end(on)); - return on; -} - -template< class Container, class Pred > -inline Container& remove_erase_if( Container& on, Pred pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - on.erase( - std::remove_if(boost::begin(on), boost::end(on), pred), - boost::end(on)); - return on; -} - -template< class Container > -inline Container& unique_erase( Container& on) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - on.erase( - std::unique(boost::begin(on), boost::end(on)), - boost::end(on)); - return on; -} - -template< class Container, class Pred > -inline Container& unique_erase( Container& on, Pred pred ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - on.erase( - std::unique(boost::begin(on), boost::end(on), pred), - boost::end(on)); - return on; -} - - } // namespace range - using range::erase; - using range::remove_erase; - using range::remove_erase_if; - using range::unique_erase; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/for_each.hpp b/boost/range/algorithm_ext/for_each.hpp deleted file mode 100644 index a470e2b..0000000 --- a/boost/range/algorithm_ext/for_each.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_FOR_EACH_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_FOR_EACH_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range_detail - { - template - inline Fn2 for_each_impl(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, InputIterator2 last2, - Fn2 fn) - { - for (; first1 != last1 && first2 != last2; ++first1, ++first2) - { - fn(*first1, *first2); - } - return fn; - } - } - - namespace range - { - template - inline Fn2 for_each(const SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::for_each_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), fn); - } - - template - inline Fn2 for_each(const SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::for_each_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), fn); - } - - template - inline Fn2 for_each(SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::for_each_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), fn); - } - - template - inline Fn2 for_each(SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) - { - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - return ::boost::range_detail::for_each_impl( - ::boost::begin(rng1), ::boost::end(rng1), - ::boost::begin(rng2), ::boost::end(rng2), fn); - } - } // namespace range - using range::for_each; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/insert.hpp b/boost/range/algorithm_ext/insert.hpp deleted file mode 100644 index 51f1b8e..0000000 --- a/boost/range/algorithm_ext/insert.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_INSERT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_INSERT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class Container, class Range > -inline Container& insert( Container& on, - BOOST_DEDUCED_TYPENAME Container::iterator before, - const Range& from ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - on.insert( before, boost::begin(from), boost::end(from) ); - return on; -} - -template< class Container, class Range > -inline Container& insert( Container& on, const Range& from ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - on.insert(boost::begin(from), boost::end(from)); - return on; -} - - } // namespace range - using range::insert; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/iota.hpp b/boost/range/algorithm_ext/iota.hpp deleted file mode 100644 index f7af446..0000000 --- a/boost/range/algorithm_ext/iota.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED - -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class ForwardRange, class Value > -inline ForwardRange& iota( ForwardRange& rng, Value x ) -{ - BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); - typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; - - iterator_t last_target = ::boost::end(rng); - for (iterator_t target = ::boost::begin(rng); target != last_target; ++target, ++x) - *target = x; - - return rng; -} - -template< class ForwardRange, class Value > -inline const ForwardRange& iota( const ForwardRange& rng, Value x ) -{ - BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); - typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; - - iterator_t last_target = ::boost::end(rng); - for (iterator_t target = ::boost::begin(rng); target != last_target; ++target, ++x) - *target = x; - - return rng; -} - - } // namespace range - using range::iota; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/is_sorted.hpp b/boost/range/algorithm_ext/is_sorted.hpp deleted file mode 100644 index 3d00729..0000000 --- a/boost/range/algorithm_ext/is_sorted.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright Bryce Lelbach 2010 -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_IS_SORTED_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_IS_SORTED_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -/// \brief template function is_sorted -/// -/// range-based version of the is_sorted std algorithm -/// -/// \pre SinglePassRange is a model of the SinglePassRangeConcept -template -inline bool is_sorted(const SinglePassRange& rng) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((LessThanComparableConcept::type>)); - return ::boost::detail::is_sorted(boost::begin(rng), boost::end(rng)); -} - -/// \overload -template -inline bool is_sorted(const SinglePassRange& rng, BinaryPredicate pred) -{ - BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); - BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, - BOOST_DEDUCED_TYPENAME range_value::type>)); - return ::boost::detail::is_sorted(boost::begin(rng), boost::end(rng), pred); -} - - } // namespace range - -using range::is_sorted; - -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/overwrite.hpp b/boost/range/algorithm_ext/overwrite.hpp deleted file mode 100644 index f84f6ea..0000000 --- a/boost/range/algorithm_ext/overwrite.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_OVERWRITE_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_OVERWRITE_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class SinglePassRange1, class SinglePassRange2 > -inline void overwrite( const SinglePassRange1& from, SinglePassRange2& to ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - BOOST_DEDUCED_TYPENAME range_iterator::type - i = boost::begin(from), e = boost::end(from); - - BOOST_DEDUCED_TYPENAME range_iterator::type - out = boost::begin(to); - -#ifndef NDEBUG - BOOST_DEDUCED_TYPENAME range_iterator::type - last_out = boost::end(to); -#endif - - for( ; i != e; ++out, ++i ) - { -#ifndef NDEBUG - BOOST_ASSERT( out != last_out - && "out of bounds in boost::overwrite()" ); -#endif - *out = *i; - } -} - -template< class SinglePassRange1, class SinglePassRange2 > -inline void overwrite( const SinglePassRange1& from, const SinglePassRange2& to ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - - BOOST_DEDUCED_TYPENAME range_iterator::type - i = boost::begin(from), e = boost::end(from); - - BOOST_DEDUCED_TYPENAME range_iterator::type - out = boost::begin(to); - -#ifndef NDEBUG - BOOST_DEDUCED_TYPENAME range_iterator::type - last_out = boost::end(to); -#endif - - for( ; i != e; ++out, ++i ) - { -#ifndef NDEBUG - BOOST_ASSERT( out != last_out - && "out of bounds in boost::overwrite()" ); -#endif - *out = *i; - } -} - - } // namespace range - using range::overwrite; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/push_back.hpp b/boost/range/algorithm_ext/push_back.hpp deleted file mode 100644 index 6fb9b9b..0000000 --- a/boost/range/algorithm_ext/push_back.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_PUSH_BACK_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_PUSH_BACK_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class Container, class Range > -inline Container& push_back( Container& on, const Range& from ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from), - "cannot copy from a container to itself"); - on.insert( on.end(), boost::begin(from), boost::end(from) ); - return on; -} - - } // namespace range - using range::push_back; -} // namespace boost - -#endif // include guard diff --git a/boost/range/algorithm_ext/push_front.hpp b/boost/range/algorithm_ext/push_front.hpp deleted file mode 100644 index e893098..0000000 --- a/boost/range/algorithm_ext/push_front.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Boost.Range library -// -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_ALGORITHM_EXT_PUSH_FRONT_HPP_INCLUDED -#define BOOST_RANGE_ALGORITHM_EXT_PUSH_FRONT_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include - -namespace boost -{ - namespace range - { - -template< class Container, class Range > -inline Container& push_front( Container& on, const Range& from ) -{ - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); - BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from), - "cannot copy from a container to itself"); - on.insert( on.begin(), boost::begin(from), boost::end(from) ); - return on; -} - - } // namespace range - using range::push_front; -} // namespace boost - -#endif // include guard diff --git a/boost/range/detail/less.hpp b/boost/range/detail/less.hpp deleted file mode 100644 index 957c5b6..0000000 --- a/boost/range/detail/less.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright 2019 Glen Joseph Fernandes -(glenjofe@gmail.com) - -Distributed under the Boost Software License, Version 1.0. -(http://www.boost.org/LICENSE_1_0.txt) -*/ -#ifndef BOOST_RANGE_DETAIL_LESS -#define BOOST_RANGE_DETAIL_LESS - -namespace boost { -namespace range { -namespace detail { - -struct less { - template - bool operator()(const T& lhs, const U& rhs) const { - return lhs < rhs; - } -}; - -} /* detail */ -} /* range */ -} /* boost */ - -#endif diff --git a/boost/range/detail/range_return.hpp b/boost/range/detail/range_return.hpp deleted file mode 100644 index 9b98e09..0000000 --- a/boost/range/detail/range_return.hpp +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright Neil Groves 2009. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// -// For more information, see http://www.boost.org/libs/range/ -// -#ifndef BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED -#define BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED - -#include -#include -#include -#include - -namespace boost -{ - enum range_return_value - { - // (*) indicates the most common values - return_found, // only the found resulting iterator (*) - return_next, // next(found) iterator - return_prior, // prior(found) iterator - return_begin_found, // [begin, found) range (*) - return_begin_next, // [begin, next(found)) range - return_begin_prior, // [begin, prior(found)) range - return_found_end, // [found, end) range (*) - return_next_end, // [next(found), end) range - return_prior_end, // [prior(found), end) range - return_begin_end // [begin, end) range - }; - - template< class SinglePassRange, range_return_value > - struct range_return - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - SinglePassRange& rng) - { - return type(found, boost::end(rng)); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_found > - { - typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; - - static type pack(type found, SinglePassRange&) - { - return found; - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_next > - { - typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; - - static type pack(type found, SinglePassRange& rng) - { - return found == boost::end(rng) - ? found - : boost::next(found); - } - }; - - template< class BidirectionalRange > - struct range_return< BidirectionalRange, return_prior > - { - typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; - - static type pack(type found, BidirectionalRange& rng) - { - return found == boost::begin(rng) - ? found - : boost::prior(found); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_begin_found > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - SinglePassRange& rng) - { - return type(boost::begin(rng), found); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_begin_next > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - SinglePassRange& rng) - { - return type( boost::begin(rng), - found == boost::end(rng) ? found : boost::next(found) ); - } - }; - - template< class BidirectionalRange > - struct range_return< BidirectionalRange, return_begin_prior > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - BidirectionalRange& rng) - { - return type( boost::begin(rng), - found == boost::begin(rng) ? found : boost::prior(found) ); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_found_end > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - SinglePassRange& rng) - { - return type(found, boost::end(rng)); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_next_end > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - SinglePassRange& rng) - { - return type( found == boost::end(rng) ? found : boost::next(found), - boost::end(rng) ); - } - }; - - template< class BidirectionalRange > - struct range_return< BidirectionalRange, return_prior_end > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, - BidirectionalRange& rng) - { - return type( found == boost::begin(rng) ? found : boost::prior(found), - boost::end(rng) ); - } - }; - - template< class SinglePassRange > - struct range_return< SinglePassRange, return_begin_end > - { - typedef boost::iterator_range< - BOOST_DEDUCED_TYPENAME range_iterator::type > type; - - static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type, - SinglePassRange& rng) - { - return type(boost::begin(rng), boost::end(rng)); - } - }; - -} - -#endif // include guard diff --git a/boost/ratio/config.hpp b/boost/ratio/config.hpp index 29f7e0c..1c3dd3c 100644 --- a/boost/ratio/config.hpp +++ b/boost/ratio/config.hpp @@ -11,6 +11,7 @@ #include #include +#include #include @@ -25,7 +26,7 @@ #if !defined BOOST_RATIO_VERSION -#define BOOST_RATIO_VERSION 1 +#define BOOST_RATIO_VERSION 2 #else #if BOOST_RATIO_VERSION!=1 && BOOST_RATIO_VERSION!=2 #error "BOOST_RATIO_VERSION must be 1 or 2" @@ -91,7 +92,10 @@ #define BOOST_RATIO_DENOMINATOR_IS_OUT_OF_RANGE "ratio denominator is out of range" #endif +#if defined(BOOST_RATIO_EXTENSIONS) -//#define BOOST_RATIO_EXTENSIONS +BOOST_PRAGMA_MESSAGE("Support for BOOST_RATIO_EXTENSIONS is deprecated and will be removed when Boost.Ratio is implemented in terms of .") + +#endif #endif // header diff --git a/boost/ratio/detail/requires_cxx11.hpp b/boost/ratio/detail/requires_cxx11.hpp index 8341a96..1f7362e 100644 --- a/boost/ratio/detail/requires_cxx11.hpp +++ b/boost/ratio/detail/requires_cxx11.hpp @@ -15,7 +15,7 @@ defined(BOOST_NO_CXX11_NOEXCEPT) || \ defined(BOOST_NO_CXX11_HDR_RATIO) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Ratio 1.82 and will be removed in Boost.Ratio 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.Ratio 1.82 and will be removed in Boost.Ratio 1.84.") #endif diff --git a/boost/smart_ptr/detail/requires_cxx11.hpp b/boost/smart_ptr/detail/requires_cxx11.hpp index fb4d61c..732cc40 100644 --- a/boost/smart_ptr/detail/requires_cxx11.hpp +++ b/boost/smart_ptr/detail/requires_cxx11.hpp @@ -16,7 +16,7 @@ defined(BOOST_NO_CXX11_NULLPTR) || \ defined(BOOST_NO_CXX11_SMART_PTR) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.SmartPtr 1.82 and will be removed in Boost.SmartPtr 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.SmartPtr 1.82 and will be removed in Boost.SmartPtr 1.84. Please open an issue in https://github.com/boostorg/smart_ptr if you want it retained.") #endif diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp index 99ded0d..57de800 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp @@ -137,7 +137,7 @@ public: long use_count() const // nothrow { - return atomic_load( &use_count_ ); + return static_cast( atomic_load( &use_count_ ) ); } }; diff --git a/boost/smart_ptr/detail/sp_thread_pause.hpp b/boost/smart_ptr/detail/sp_thread_pause.hpp deleted file mode 100644 index 2cddd90..0000000 --- a/boost/smart_ptr/detail/sp_thread_pause.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED -#define BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED - -// MS compatible compilers support #pragma once - -#if defined(_MSC_VER) && (_MSC_VER >= 1020) -# pragma once -#endif - -// boost/smart_ptr/detail/sp_thread_pause.hpp -// -// inline void bost::detail::sp_thread_pause(); -// -// Emits a "pause" instruction. -// -// Copyright 2008, 2020 Peter Dimov -// Distributed under the Boost Software License, Version 1.0 -// https://www.boost.org/LICENSE_1_0.txt - -#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__) - -extern "C" void _mm_pause(); - -#define BOOST_SP_PAUSE _mm_pause(); - -#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) ) - -#define BOOST_SP_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" ); - -#else - -#define BOOST_SP_PAUSE - -#endif - -namespace boost -{ -namespace detail -{ - -inline void sp_thread_pause() -{ - BOOST_SP_PAUSE -} - -} // namespace detail -} // namespace boost - -#undef BOOST_SP_PAUSE - -#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/yield_k.hpp b/boost/smart_ptr/detail/yield_k.hpp index d9a1b46..7f6c645 100644 --- a/boost/smart_ptr/detail/yield_k.hpp +++ b/boost/smart_ptr/detail/yield_k.hpp @@ -19,9 +19,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include -#include -#include +#include namespace boost { @@ -34,13 +32,13 @@ inline void yield( unsigned k ) // Experiments on Windows and Fedora 32 show that a single pause, // followed by an immediate sp_thread_sleep(), is best. - if( k == 0 ) + if( k & 1 ) { - sp_thread_pause(); + boost::core::sp_thread_sleep(); } else { - sp_thread_sleep(); + boost::core::sp_thread_pause(); } } diff --git a/boost/smart_ptr/intrusive_ref_counter.hpp b/boost/smart_ptr/intrusive_ref_counter.hpp new file mode 100644 index 0000000..c2f918d --- /dev/null +++ b/boost/smart_ptr/intrusive_ref_counter.hpp @@ -0,0 +1,188 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file intrusive_ref_counter.hpp + * \author Andrey Semashev + * \date 12.03.2009 + * + * This header contains a reference counter class for \c intrusive_ptr. + */ + +#ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ +#define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(_MSC_VER) +#pragma warning(push) +// This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter: +// 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template +// Note that there is no inline specifier in the declarations. +#pragma warning(disable: 4396) +#endif + +namespace boost { + +namespace sp_adl_block { + +/*! + * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter + * + * The policy instructs the \c intrusive_ref_counter base class to implement + * a reference counter suitable for single threaded use only. Pointers to the same + * object with this kind of reference counter must not be used by different threads. + */ +struct thread_unsafe_counter +{ + typedef unsigned int type; + + static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT + { + return counter; + } + + static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT + { + ++counter; + } + + static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT + { + return --counter; + } +}; + +/*! + * \brief Thread safe reference counter policy for \c intrusive_ref_counter + * + * The policy instructs the \c intrusive_ref_counter base class to implement + * a thread-safe reference counter, if the target platform supports multithreading. + */ +struct thread_safe_counter +{ + typedef boost::detail::atomic_count type; + + static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT + { + return static_cast< unsigned int >(static_cast< long >(counter)); + } + + static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT + { + ++counter; + } + + static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT + { + return static_cast< unsigned int >(--counter); + } +}; + +template< typename DerivedT, typename CounterPolicyT = thread_safe_counter > +class intrusive_ref_counter; + +template< typename DerivedT, typename CounterPolicyT > +void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; +template< typename DerivedT, typename CounterPolicyT > +void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; + +/*! + * \brief A reference counter base class + * + * This base class can be used with user-defined classes to add support + * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT. + * Upon releasing the last \c intrusive_ptr referencing the object + * derived from the \c intrusive_ref_counter class, operator \c delete + * is automatically called on the pointer to the object. + * + * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter. + */ +template< typename DerivedT, typename CounterPolicyT > +class intrusive_ref_counter +{ +private: + //! Reference counter type + typedef typename CounterPolicyT::type counter_type; + //! Reference counter + mutable counter_type m_ref_counter; + +public: + /*! + * Default constructor + * + * \post use_count() == 0 + */ + intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0) + { + } + + /*! + * Copy constructor + * + * \post use_count() == 0 + */ + intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0) + { + } + + /*! + * Assignment + * + * \post The reference counter is not modified after assignment + */ + intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; } + + /*! + * \return The reference counter + */ + unsigned int use_count() const BOOST_SP_NOEXCEPT + { + return CounterPolicyT::load(m_ref_counter); + } + +protected: + /*! + * Destructor + */ + BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {}) + + friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; + friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; +}; + +template< typename DerivedT, typename CounterPolicyT > +inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT +{ + CounterPolicyT::increment(p->m_ref_counter); +} + +template< typename DerivedT, typename CounterPolicyT > +inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT +{ + if (CounterPolicyT::decrement(p->m_ref_counter) == 0) + delete static_cast< const DerivedT* >(p); +} + +} // namespace sp_adl_block + +using sp_adl_block::intrusive_ref_counter; +using sp_adl_block::thread_unsafe_counter; +using sp_adl_block::thread_safe_counter; + +} // namespace boost + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ diff --git a/boost/stacktrace/frame.hpp b/boost/stacktrace/frame.hpp index d3c0fd1..965c895 100644 --- a/boost/stacktrace/frame.hpp +++ b/boost/stacktrace/frame.hpp @@ -12,6 +12,24 @@ # pragma once #endif +#include +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || \ + defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \ + defined(BOOST_NO_CXX11_CONSTEXPR) || \ + defined(BOOST_NO_CXX11_NULLPTR) || \ + defined(BOOST_NO_CXX11_NOEXCEPT) || \ + defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \ + defined(BOOST_NO_CXX11_FINAL) || \ + defined(BOOST_NO_CXX11_ALIGNOF) || \ + defined(BOOST_NO_CXX11_STATIC_ASSERT) || \ + defined(BOOST_NO_CXX11_SMART_PTR) || \ + defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) || \ + defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + +BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Stacktrace 1.82 and will be removed in Boost.Stacktrace 1.84.") + +#endif + #include #include diff --git a/boost/system/detail/mutex.hpp b/boost/system/detail/mutex.hpp index 4c2b0fa..c27e08a 100644 --- a/boost/system/detail/mutex.hpp +++ b/boost/system/detail/mutex.hpp @@ -31,7 +31,9 @@ struct mutex } // namespace system } // namespace boost -#elif defined(BOOST_MSSTL_VERSION) && BOOST_MSSTL_VERSION >= 140 +#else // defined(BOOST_SYSTEM_DISABLE_THREADS) + +#if defined(BOOST_MSSTL_VERSION) && BOOST_MSSTL_VERSION >= 140 // Under the MS STL, std::mutex::mutex() is not constexpr, as is // required by the standard, which leads to initialization order @@ -40,6 +42,14 @@ struct mutex #include +#if BOOST_MSSTL_VERSION >= 142 || _HAS_SHARED_MUTEX +# define BOOST_SYSTEM_HAS_MSSTL_SHARED_MUTEX +#endif + +#endif + +#if defined(BOOST_SYSTEM_HAS_MSSTL_SHARED_MUTEX) + namespace boost { namespace system @@ -53,7 +63,7 @@ typedef std::shared_mutex mutex; } // namespace system } // namespace boost -#else +#else // defined(BOOST_SYSTEM_HAS_MSSTL_SHARED_MUTEX) #include @@ -70,7 +80,8 @@ using std::mutex; } // namespace system } // namespace boost -#endif +#endif // defined(BOOST_SYSTEM_HAS_MSSTL_SHARED_MUTEX) +#endif // defined(BOOST_SYSTEM_DISABLE_THREADS) namespace boost { diff --git a/boost/system/detail/requires_cxx11.hpp b/boost/system/detail/requires_cxx11.hpp index 1bf6a1f..40cf2c2 100644 --- a/boost/system/detail/requires_cxx11.hpp +++ b/boost/system/detail/requires_cxx11.hpp @@ -14,7 +14,7 @@ defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || \ defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.System 1.82 and will be removed in Boost.System 1.84.") +BOOST_PRAGMA_MESSAGE("C++03 support was deprecated in Boost.System 1.82 and will be removed in Boost.System 1.84. Please open an issue in https://github.com/boostorg/system if you want it retained.") #endif diff --git a/boost/system/result.hpp b/boost/system/result.hpp index 4084ca8..08eb899 100644 --- a/boost/system/result.hpp +++ b/boost/system/result.hpp @@ -401,12 +401,18 @@ public: // error access - constexpr E error() const + constexpr E error() const & noexcept( std::is_nothrow_default_constructible::value && std::is_nothrow_copy_constructible::value ) { return has_error()? variant2::unsafe_get<1>( v_ ): E(); } + BOOST_CXX14_CONSTEXPR E error() && + noexcept( std::is_nothrow_default_constructible::value && std::is_nothrow_move_constructible::value ) + { + return has_error()? std::move( variant2::unsafe_get<1>( v_ ) ): E(); + } + // emplace template @@ -581,12 +587,18 @@ public: // error access - constexpr E error() const + constexpr E error() const & noexcept( std::is_nothrow_default_constructible::value && std::is_nothrow_copy_constructible::value ) { return has_error()? variant2::unsafe_get<1>( v_ ): E(); } + BOOST_CXX14_CONSTEXPR E error() && + noexcept( std::is_nothrow_default_constructible::value && std::is_nothrow_move_constructible::value ) + { + return has_error()? std::move( variant2::unsafe_get<1>( v_ ) ): E(); + } + // emplace BOOST_CXX14_CONSTEXPR void emplace() diff --git a/boost/throw_exception.hpp b/boost/throw_exception.hpp index cdda86b..7c7fcbd 100644 --- a/boost/throw_exception.hpp +++ b/boost/throw_exception.hpp @@ -104,9 +104,9 @@ public: copy_from( &e ); set_info( *this, throw_file( loc.file_name() ) ); - set_info( *this, throw_line( loc.line() ) ); + set_info( *this, throw_line( static_cast( loc.line() ) ) ); set_info( *this, throw_function( loc.function_name() ) ); - set_info( *this, throw_column( loc.column() ) ); + set_info( *this, throw_column( static_cast( loc.column() ) ) ); } virtual boost::exception_detail::clone_base const * clone() const BOOST_OVERRIDE diff --git a/boost/token_functions.hpp b/boost/token_functions.hpp deleted file mode 100644 index 22d4a33..0000000 --- a/boost/token_functions.hpp +++ /dev/null @@ -1,653 +0,0 @@ -// Boost token_functions.hpp ------------------------------------------------// - -// Copyright John R. Bandela 2001. - -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/tokenizer/ for documentation. - -// Revision History: -// 01 Oct 2004 Joaquin M Lopez Munoz -// Workaround for a problem with string::assign in msvc-stlport -// 06 Apr 2004 John Bandela -// Fixed a bug involving using char_delimiter with a true input iterator -// 28 Nov 2003 Robert Zeh and John Bandela -// Converted into "fast" functions that avoid using += when -// the supplied iterator isn't an input_iterator; based on -// some work done at Archelon and a version that was checked into -// the boost CVS for a short period of time. -// 20 Feb 2002 John Maddock -// Removed using namespace std declarations and added -// workaround for BOOST_NO_STDC_NAMESPACE (the library -// can be safely mixed with regex). -// 06 Feb 2002 Jeremy Siek -// Added char_separator. -// 02 Feb 2002 Jeremy Siek -// Removed tabs and a little cleanup. - - -#ifndef BOOST_TOKEN_FUNCTIONS_JRB120303_HPP_ -#define BOOST_TOKEN_FUNCTIONS_JRB120303_HPP_ - -#include -#include -#include -#include -#include // for find_if -#include -#include -#include -#include -#include -#include -#if !defined(BOOST_NO_CWCTYPE) -#include -#endif - -// -// the following must not be macros if we are to prefix them -// with std:: (they shouldn't be macros anyway...) -// -#ifdef ispunct -# undef ispunct -#endif -#ifdef iswpunct -# undef iswpunct -#endif -#ifdef isspace -# undef isspace -#endif -#ifdef iswspace -# undef iswspace -#endif -// -// fix namespace problems: -// -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std{ - using ::ispunct; - using ::isspace; -#if !defined(BOOST_NO_CWCTYPE) - using ::iswpunct; - using ::iswspace; -#endif -} -#endif - -namespace boost{ - //=========================================================================== - // The escaped_list_separator class. Which is a model of TokenizerFunction - // An escaped list is a super-set of what is commonly known as a comma - // separated value (csv) list.It is separated into fields by a comma or - // other character. If the delimiting character is inside quotes, then it is - // counted as a regular character.To allow for embedded quotes in a field, - // there can be escape sequences using the \ much like C. - // The role of the comma, the quotation mark, and the escape - // character (backslash \), can be assigned to other characters. - - struct escaped_list_error : public std::runtime_error{ - escaped_list_error(const std::string& what_arg):std::runtime_error(what_arg) { } - }; - - -// The out of the box GCC 2.95 on cygwin does not have a char_traits class. -// MSVC does not like the following typename - template ::traits_type > - class escaped_list_separator { - - private: - typedef std::basic_string string_type; - struct char_eq { - Char e_; - char_eq(Char e):e_(e) { } - bool operator()(Char c) { - return Traits::eq(e_,c); - } - }; - string_type escape_; - string_type c_; - string_type quote_; - bool last_; - - bool is_escape(Char e) { - char_eq f(e); - return std::find_if(escape_.begin(),escape_.end(),f)!=escape_.end(); - } - bool is_c(Char e) { - char_eq f(e); - return std::find_if(c_.begin(),c_.end(),f)!=c_.end(); - } - bool is_quote(Char e) { - char_eq f(e); - return std::find_if(quote_.begin(),quote_.end(),f)!=quote_.end(); - } - template - void do_escape(iterator& next,iterator end,Token& tok) { - if (++next == end) - BOOST_THROW_EXCEPTION(escaped_list_error(std::string("cannot end with escape"))); - if (Traits::eq(*next,'n')) { - tok+='\n'; - return; - } - else if (is_quote(*next)) { - tok+=*next; - return; - } - else if (is_c(*next)) { - tok+=*next; - return; - } - else if (is_escape(*next)) { - tok+=*next; - return; - } - else - BOOST_THROW_EXCEPTION(escaped_list_error(std::string("unknown escape sequence"))); - } - - public: - - explicit escaped_list_separator(Char e = '\\', - Char c = ',',Char q = '\"') - : escape_(1,e), c_(1,c), quote_(1,q), last_(false) { } - - escaped_list_separator(string_type e, string_type c, string_type q) - : escape_(e), c_(c), quote_(q), last_(false) { } - - void reset() {last_=false;} - - template - bool operator()(InputIterator& next,InputIterator end,Token& tok) { - bool bInQuote = false; - tok = Token(); - - if (next == end) { - if (last_) { - last_ = false; - return true; - } - else - return false; - } - last_ = false; - for (;next != end;++next) { - if (is_escape(*next)) { - do_escape(next,end,tok); - } - else if (is_c(*next)) { - if (!bInQuote) { - // If we are not in quote, then we are done - ++next; - // The last character was a c, that means there is - // 1 more blank field - last_ = true; - return true; - } - else tok+=*next; - } - else if (is_quote(*next)) { - bInQuote=!bInQuote; - } - else { - tok += *next; - } - } - return true; - } - }; - - //=========================================================================== - // The classes here are used by offset_separator and char_separator to implement - // faster assigning of tokens using assign instead of += - - namespace tokenizer_detail { - //=========================================================================== - // Tokenizer was broken for wide character separators, at least on Windows, since - // CRT functions isspace etc only expect values in [0, 0xFF]. Debug build asserts - // if higher values are passed in. The traits extension class should take care of this. - // Assuming that the conditional will always get optimized out in the function - // implementations, argument types are not a problem since both forms of character classifiers - // expect an int. - -#if !defined(BOOST_NO_CWCTYPE) - template - struct traits_extension_details : public traits { - typedef typename traits::char_type char_type; - static bool isspace(char_type c) - { - return std::iswspace(c) != 0; - } - static bool ispunct(char_type c) - { - return std::iswpunct(c) != 0; - } - }; - - template - struct traits_extension_details : public traits { - typedef typename traits::char_type char_type; - static bool isspace(char_type c) - { - return std::isspace(c) != 0; - } - static bool ispunct(char_type c) - { - return std::ispunct(c) != 0; - } - }; -#endif - - - // In case there is no cwctype header, we implement the checks manually. - // We make use of the fact that the tested categories should fit in ASCII. - template - struct traits_extension : public traits { - typedef typename traits::char_type char_type; - static bool isspace(char_type c) - { -#if !defined(BOOST_NO_CWCTYPE) - return traits_extension_details::isspace(c); -#else - return static_cast< unsigned >(c) <= 255 && std::isspace(c) != 0; -#endif - } - - static bool ispunct(char_type c) - { -#if !defined(BOOST_NO_CWCTYPE) - return traits_extension_details::ispunct(c); -#else - return static_cast< unsigned >(c) <= 255 && std::ispunct(c) != 0; -#endif - } - }; - - // The assign_or_plus_equal struct contains functions that implement - // assign, +=, and clearing based on the iterator type. The - // generic case does nothing for plus_equal and clearing, while - // passing through the call for assign. - // - // When an input iterator is being used, the situation is reversed. - // The assign method does nothing, plus_equal invokes operator +=, - // and the clearing method sets the supplied token to the default - // token constructor's result. - // - - template - struct assign_or_plus_equal { - template - static void assign(Iterator b, Iterator e, Token &t) { - t.assign(b, e); - } - - template - static void plus_equal(Token &, const Value &) { } - - // If we are doing an assign, there is no need for the - // the clear. - // - template - static void clear(Token &) { } - }; - - template <> - struct assign_or_plus_equal { - template - static void assign(Iterator , Iterator , Token &) { } - template - static void plus_equal(Token &t, const Value &v) { - t += v; - } - template - static void clear(Token &t) { - t = Token(); - } - }; - - - template - struct pointer_iterator_category{ - typedef std::random_access_iterator_tag type; - }; - - - template - struct class_iterator_category{ - typedef typename Iterator::iterator_category type; - }; - - - - // This portably gets the iterator_tag without partial template specialization - template - struct get_iterator_category{ - typedef typename conditional::value, - pointer_iterator_category, - class_iterator_category - >::type cat; - - typedef typename cat::type iterator_category; - }; - - - } // namespace tokenizer_detail - - - //=========================================================================== - // The offset_separator class, which is a model of TokenizerFunction. - // Offset breaks a string into tokens based on a range of offsets - - class offset_separator { - private: - - std::vector offsets_; - unsigned int current_offset_; - bool wrap_offsets_; - bool return_partial_last_; - - public: - template - offset_separator(Iter begin, Iter end, bool wrap_offsets = true, - bool return_partial_last = true) - : offsets_(begin,end), current_offset_(0), - wrap_offsets_(wrap_offsets), - return_partial_last_(return_partial_last) { } - - offset_separator() - : offsets_(1,1), current_offset_(), - wrap_offsets_(true), return_partial_last_(true) { } - - void reset() { - current_offset_ = 0; - } - - template - bool operator()(InputIterator& next, InputIterator end, Token& tok) - { - typedef tokenizer_detail::assign_or_plus_equal< - BOOST_DEDUCED_TYPENAME tokenizer_detail::get_iterator_category< - InputIterator - >::iterator_category - > assigner; - - BOOST_ASSERT(!offsets_.empty()); - - assigner::clear(tok); - InputIterator start(next); - - if (next == end) - return false; - - if (current_offset_ == offsets_.size()) - { - if (wrap_offsets_) - current_offset_=0; - else - return false; - } - - int c = offsets_[current_offset_]; - int i = 0; - for (; i < c; ++i) { - if (next == end)break; - assigner::plus_equal(tok,*next++); - } - assigner::assign(start,next,tok); - - if (!return_partial_last_) - if (i < (c-1) ) - return false; - - ++current_offset_; - return true; - } - }; - - - //=========================================================================== - // The char_separator class breaks a sequence of characters into - // tokens based on the character delimiters (very much like bad old - // strtok). A delimiter character can either be kept or dropped. A - // kept delimiter shows up as an output token, whereas a dropped - // delimiter does not. - - // This class replaces the char_delimiters_separator class. The - // constructor for the char_delimiters_separator class was too - // confusing and needed to be deprecated. However, because of the - // default arguments to the constructor, adding the new constructor - // would cause ambiguity, so instead I deprecated the whole class. - // The implementation of the class was also simplified considerably. - - enum empty_token_policy { drop_empty_tokens, keep_empty_tokens }; - - // The out of the box GCC 2.95 on cygwin does not have a char_traits class. - template ::traits_type > - class char_separator - { - typedef tokenizer_detail::traits_extension Traits; - typedef std::basic_string string_type; - public: - explicit - char_separator(const Char* dropped_delims, - const Char* kept_delims = 0, - empty_token_policy empty_tokens = drop_empty_tokens) - : m_dropped_delims(dropped_delims), - m_use_ispunct(false), - m_use_isspace(false), - m_empty_tokens(empty_tokens), - m_output_done(false) - { - // Borland workaround - if (kept_delims) - m_kept_delims = kept_delims; - } - - // use ispunct() for kept delimiters and isspace for dropped. - explicit - char_separator() - : m_use_ispunct(true), - m_use_isspace(true), - m_empty_tokens(drop_empty_tokens), - m_output_done(false) { } - - void reset() { } - - template - bool operator()(InputIterator& next, InputIterator end, Token& tok) - { - typedef tokenizer_detail::assign_or_plus_equal< - BOOST_DEDUCED_TYPENAME tokenizer_detail::get_iterator_category< - InputIterator - >::iterator_category - > assigner; - - assigner::clear(tok); - - // skip past all dropped_delims - if (m_empty_tokens == drop_empty_tokens) - for (; next != end && is_dropped(*next); ++next) - { } - - InputIterator start(next); - - if (m_empty_tokens == drop_empty_tokens) { - - if (next == end) - return false; - - - // if we are on a kept_delims move past it and stop - if (is_kept(*next)) { - assigner::plus_equal(tok,*next); - ++next; - } else - // append all the non delim characters - for (; next != end && !is_dropped(*next) && !is_kept(*next); ++next) - assigner::plus_equal(tok,*next); - } - else { // m_empty_tokens == keep_empty_tokens - - // Handle empty token at the end - if (next == end) - { - if (m_output_done == false) - { - m_output_done = true; - assigner::assign(start,next,tok); - return true; - } - else - return false; - } - - if (is_kept(*next)) { - if (m_output_done == false) - m_output_done = true; - else { - assigner::plus_equal(tok,*next); - ++next; - m_output_done = false; - } - } - else if (m_output_done == false && is_dropped(*next)) { - m_output_done = true; - } - else { - if (is_dropped(*next)) - start=++next; - for (; next != end && !is_dropped(*next) && !is_kept(*next); ++next) - assigner::plus_equal(tok,*next); - m_output_done = true; - } - } - assigner::assign(start,next,tok); - return true; - } - - private: - string_type m_kept_delims; - string_type m_dropped_delims; - bool m_use_ispunct; - bool m_use_isspace; - empty_token_policy m_empty_tokens; - bool m_output_done; - - bool is_kept(Char E) const - { - if (m_kept_delims.length()) - return m_kept_delims.find(E) != string_type::npos; - else if (m_use_ispunct) { - return Traits::ispunct(E) != 0; - } else - return false; - } - bool is_dropped(Char E) const - { - if (m_dropped_delims.length()) - return m_dropped_delims.find(E) != string_type::npos; - else if (m_use_isspace) { - return Traits::isspace(E) != 0; - } else - return false; - } - }; - - //=========================================================================== - // The following class is DEPRECATED, use class char_separators instead. - // - // The char_delimiters_separator class, which is a model of - // TokenizerFunction. char_delimiters_separator breaks a string - // into tokens based on character delimiters. There are 2 types of - // delimiters. returnable delimiters can be returned as - // tokens. These are often punctuation. nonreturnable delimiters - // cannot be returned as tokens. These are often whitespace - - // The out of the box GCC 2.95 on cygwin does not have a char_traits class. - template ::traits_type > - class char_delimiters_separator { - private: - - typedef tokenizer_detail::traits_extension Traits; - typedef std::basic_string string_type; - string_type returnable_; - string_type nonreturnable_; - bool return_delims_; - bool no_ispunct_; - bool no_isspace_; - - bool is_ret(Char E)const - { - if (returnable_.length()) - return returnable_.find(E) != string_type::npos; - else{ - if (no_ispunct_) {return false;} - else{ - int r = Traits::ispunct(E); - return r != 0; - } - } - } - bool is_nonret(Char E)const - { - if (nonreturnable_.length()) - return nonreturnable_.find(E) != string_type::npos; - else{ - if (no_isspace_) {return false;} - else{ - int r = Traits::isspace(E); - return r != 0; - } - } - } - - public: - explicit char_delimiters_separator(bool return_delims = false, - const Char* returnable = 0, - const Char* nonreturnable = 0) - : returnable_(returnable ? returnable : string_type().c_str()), - nonreturnable_(nonreturnable ? nonreturnable:string_type().c_str()), - return_delims_(return_delims), no_ispunct_(returnable!=0), - no_isspace_(nonreturnable!=0) { } - - void reset() { } - - public: - - template - bool operator()(InputIterator& next, InputIterator end,Token& tok) { - tok = Token(); - - // skip past all nonreturnable delims - // skip past the returnable only if we are not returning delims - for (;next!=end && ( is_nonret(*next) || (is_ret(*next) - && !return_delims_ ) );++next) { } - - if (next == end) { - return false; - } - - // if we are to return delims and we are one a returnable one - // move past it and stop - if (is_ret(*next) && return_delims_) { - tok+=*next; - ++next; - } - else - // append all the non delim characters - for (;next!=end && !is_nonret(*next) && !is_ret(*next);++next) - tok+=*next; - - - return true; - } - }; - - -} //namespace boost - -#endif diff --git a/boost/token_iterator.hpp b/boost/token_iterator.hpp deleted file mode 100644 index 42945d7..0000000 --- a/boost/token_iterator.hpp +++ /dev/null @@ -1,131 +0,0 @@ -// Boost token_iterator.hpp -------------------------------------------------// - -// Copyright John R. Bandela 2001 -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/tokenizer for documentation. - -// Revision History: -// 16 Jul 2003 John Bandela -// Allowed conversions from convertible base iterators -// 03 Jul 2003 John Bandela -// Converted to new iterator adapter - - - -#ifndef BOOST_TOKENIZER_POLICY_JRB070303_HPP_ -#define BOOST_TOKENIZER_POLICY_JRB070303_HPP_ - -#include -#include -#include -#include -#include - -namespace boost -{ - template - class token_iterator - : public iterator_facade< - token_iterator - , Type - , typename iterators::minimum_category< - forward_traversal_tag - , typename iterator_traversal::type - >::type - , const Type& - > - { - -#ifdef __DCC__ - friend class boost::iterator_core_access; -#else - friend class iterator_core_access; -#endif - TokenizerFunc f_; - Iterator begin_; - Iterator end_; - bool valid_; - Type tok_; - - void increment(){ - BOOST_ASSERT(valid_); - valid_ = f_(begin_,end_,tok_); - } - - const Type& dereference() const { - BOOST_ASSERT(valid_); - return tok_; - } - template - bool equal(const Other& a) const{ - return (a.valid_ && valid_) - ?( (a.begin_==begin_) && (a.end_ == end_) ) - :(a.valid_==valid_); - - } - - void initialize(){ - if(valid_) return; - f_.reset(); - valid_ = (begin_ != end_)? - f_(begin_,end_,tok_):false; - } - public: - token_iterator():begin_(),end_(),valid_(false),tok_() { } - - token_iterator(TokenizerFunc f, Iterator begin, Iterator e = Iterator()) - : f_(f),begin_(begin),end_(e),valid_(false),tok_(){ initialize(); } - - token_iterator(Iterator begin, Iterator e = Iterator()) - : f_(),begin_(begin),end_(e),valid_(false),tok_() {initialize();} - - template - token_iterator( - token_iterator const& t - , typename enable_if_convertible::type* = 0) - : f_(t.tokenizer_function()),begin_(t.base()) - ,end_(t.end()),valid_(!t.at_end()),tok_(t.current_token()) {} - - Iterator base()const{return begin_;} - - Iterator end()const{return end_;} - - TokenizerFunc tokenizer_function()const{return f_;} - - Type current_token()const{return tok_;} - - bool at_end()const{return !valid_;} - - - - - }; - template < - class TokenizerFunc = char_delimiters_separator, - class Iterator = std::string::const_iterator, - class Type = std::string - > - class token_iterator_generator { - - private: - public: - typedef token_iterator type; - }; - - - // Type has to be first because it needs to be explicitly specified - // because there is no way the function can deduce it. - template - typename token_iterator_generator::type - make_token_iterator(Iterator begin, Iterator end,const TokenizerFunc& fun){ - typedef typename - token_iterator_generator::type ret_type; - return ret_type(fun,begin,end); - } - -} // namespace boost - -#endif diff --git a/boost/tokenizer.hpp b/boost/tokenizer.hpp deleted file mode 100644 index 081e5ba..0000000 --- a/boost/tokenizer.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Boost tokenizer.hpp -----------------------------------------------------// - -// (c) Copyright Jeremy Siek and John R. Bandela 2001. - -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/tokenizer for documenation - -// Revision History: -// 03 Jul 2003 John Bandela -// Converted to new iterator adapter -// 02 Feb 2002 Jeremy Siek -// Removed tabs and a little cleanup. - -#ifndef BOOST_TOKENIZER_JRB070303_HPP_ -#define BOOST_TOKENIZER_JRB070303_HPP_ - -#include - -namespace boost { - - - //=========================================================================== - // A container-view of a tokenized "sequence" - template < - typename TokenizerFunc = char_delimiters_separator, - typename Iterator = std::string::const_iterator, - typename Type = std::string - > - class tokenizer { - private: - typedef token_iterator_generator TGen; - - // It seems that MSVC does not like the unqualified use of iterator, - // Thus we use iter internally when it is used unqualified and - // the users of this class will always qualify iterator. - typedef typename TGen::type iter; - - public: - - typedef iter iterator; - typedef iter const_iterator; - typedef Type value_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef const pointer const_pointer; - typedef void size_type; - typedef void difference_type; - - tokenizer(Iterator first, Iterator last, - const TokenizerFunc& f = TokenizerFunc()) - : first_(first), last_(last), f_(f) { } - - template - tokenizer(const Container& c) - : first_(c.begin()), last_(c.end()), f_() { } - - template - tokenizer(const Container& c,const TokenizerFunc& f) - : first_(c.begin()), last_(c.end()), f_(f) { } - - void assign(Iterator first, Iterator last){ - first_ = first; - last_ = last; - } - - void assign(Iterator first, Iterator last, const TokenizerFunc& f){ - assign(first,last); - f_ = f; - } - - template - void assign(const Container& c){ - assign(c.begin(),c.end()); - } - - - template - void assign(const Container& c, const TokenizerFunc& f){ - assign(c.begin(),c.end(),f); - } - - iter begin() const { return iter(f_,first_,last_); } - iter end() const { return iter(f_,last_,last_); } - - private: - Iterator first_; - Iterator last_; - TokenizerFunc f_; - }; - - -} // namespace boost - -#endif diff --git a/boost/type_index.hpp b/boost/type_index.hpp deleted file mode 100644 index 056b98c..0000000 --- a/boost/type_index.hpp +++ /dev/null @@ -1,265 +0,0 @@ -// -// Copyright 2012-2023 Antony Polukhin. -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_HPP -#define BOOST_TYPE_INDEX_HPP - -/// \file boost/type_index.hpp -/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library. -/// -/// By inclusion of this file most optimal type index classes will be included and used -/// as a boost::typeindex::type_index and boost::typeindex::type_info. - -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) -# include BOOST_TYPE_INDEX_USER_TYPEINDEX -# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH -# pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX)) -# endif -#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) -# include -# if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY) -# include -# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH -# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates") -# endif -# else -# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH -# pragma detect_mismatch( "boost__type_index__abi", "RTTI is used") -# endif -# endif -#else -# include -# include -# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH -# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI") -# endif -#endif - -#ifndef BOOST_TYPE_INDEX_REGISTER_CLASS -#define BOOST_TYPE_INDEX_REGISTER_CLASS -#endif - -namespace boost { namespace typeindex { - -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - -/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE -/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to -/// deduce the name of a type. If your compiler is not recognized -/// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may -/// define this macro by yourself. -/// -/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro -/// that outputs the \b whole function signature \b including \b template \b parameters. -/// -/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined, -/// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes. -/// -/// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING -/// for an information of how to tune the implementation to make a nice pretty_name() output. -#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION - -/// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING -/// This is a helper macro for making correct pretty_names() with RTTI off. -/// -/// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to -/// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a -/// support for compilers, that by default are not recognized by TypeIndex library. -/// -/// \b Example: -/// -/// Imagine the situation when -/// \code boost::typeindex::ctti_type_index::type_id().pretty_name() \endcode -/// returns the following string: -/// \code "static const char *boost::detail::ctti::n() [T = int]" \endcode -/// and \code boost::typeindex::ctti_type_index::type_id().pretty_name() \endcode returns the following: -/// \code "static const char *boost::detail::ctti::n() [T = short]" \endcode -/// -/// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on -/// the type T. After first 39 characters we have a human readable type name which is duplicated at the end -/// of a string. String always ends on ']', which consumes 1 character. -/// -/// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to -/// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode -/// for `boost::typeindex::ctti_type_index::type_id().pretty_name()` and \code "short>::n() [T = short" \endcode -/// for `boost::typeindex::ctti_type_index::type_id().pretty_name()`. -/// -/// Now we need to take additional care of the characters that go before the last mention of our type. We'll -/// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = " -/// itself: -/// -/// \code (39, 1, true, "T = ") \endcode -/// -/// In case of GCC or Clang command line we need to add the following line while compiling all the sources: -/// -/// \code -/// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")' -/// \endcode -/// \param begin_skip How many characters must be skipped at the beginning of the type holding string. -/// Must be a compile time constant. -/// \param end_skip How many characters must be skipped at the end of the type holding string. -/// Must be a compile time constant. -/// \param runtime_skip Do we need additional checks at runtime to cut off the more characters. -/// Must be `true` or `false`. -/// \param runtime_skip_until Skip all the characters before the following string (including the string itself). -/// Must be a compile time array of characters. -/// -/// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info. -#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "") - - - /// Depending on a compiler flags, optimal implementation of type_index will be used - /// as a default boost::typeindex::type_index. - /// - /// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or - /// user defined type_index class. - /// - /// \b See boost::typeindex::type_index_facade for a full description of type_index functions. - typedef platform_specific type_index; -#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX) - // Nothing to do -#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC) - typedef boost::typeindex::stl_type_index type_index; -#else - typedef boost::typeindex::ctti_type_index type_index; -#endif - -/// Depending on a compiler flags, optimal implementation of type_info will be used -/// as a default boost::typeindex::type_info. -/// -/// Could be a std::type_info, boost::typeindex::detail::ctti_data or -/// some user defined class. -/// -/// type_info \b is \b not copyable or default constructible. It is \b not assignable too! -typedef type_index::type_info_t type_info; - -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - -/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX -/// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file -/// with user provided implementation of type_index. -/// -/// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section -/// of documentation for usage example. -#define BOOST_TYPE_INDEX_USER_TYPEINDEX - - -/// \def BOOST_TYPE_INDEX_REGISTER_CLASS -/// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI. -/// Put this macro into the public section of polymorphic class to allow runtime type detection. -/// -/// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function -/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`. -/// -/// \b Example: -/// \code -/// class A { -/// public: -/// BOOST_TYPE_INDEX_REGISTER_CLASS -/// virtual ~A(){} -/// }; -/// -/// struct B: public A { -/// BOOST_TYPE_INDEX_REGISTER_CLASS -/// }; -/// -/// struct C: public B { -/// BOOST_TYPE_INDEX_REGISTER_CLASS -/// }; -/// -/// ... -/// -/// C c1; -/// A* pc1 = &c1; -/// assert(boost::typeindex::type_id() == boost::typeindex::type_id_runtime(*pc1)); -/// \endcode -#define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions - -/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY -/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing -/// RTTI on/off modules. See -/// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html) -/// section of documentation for more info. -#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY - -#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - - -/// Function to get boost::typeindex::type_index for a type T. -/// Removes const, volatile && and & modifiers from T. -/// -/// \b Example: -/// \code -/// type_index ti = type_id(); -/// std::cout << ti.pretty_name(); // Outputs 'int' -/// \endcode -/// -/// \tparam T Type for which type_index must be created. -/// \throw Nothing. -/// \return boost::typeindex::type_index with information about the specified type T. -template -inline type_index type_id() BOOST_NOEXCEPT { - return type_index::type_id(); -} - -/// Function for constructing boost::typeindex::type_index instance for type T. -/// Does not remove const, volatile, & and && modifiers from T. -/// -/// If T has no const, volatile, & and && modifiers, then returns exactly -/// the same result as in case of calling `type_id()`. -/// -/// \b Example: -/// \code -/// type_index ti = type_id_with_cvr(); -/// std::cout << ti.pretty_name(); // Outputs 'int&' -/// \endcode -/// -/// \tparam T Type for which type_index must be created. -/// \throw Nothing. -/// \return boost::typeindex::type_index with information about the specified type T. -template -inline type_index type_id_with_cvr() BOOST_NOEXCEPT { - return type_index::type_id_with_cvr(); -} - -/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index. -/// -/// Returns runtime information about specified type. -/// -/// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS. -/// -/// \b Example: -/// \code -/// struct Base { virtual ~Base(){} }; -/// struct Derived: public Base {}; -/// ... -/// Derived d; -/// Base& b = d; -/// type_index ti = type_id_runtime(b); -/// std::cout << ti.pretty_name(); // Outputs 'Derived' -/// \endcode -/// -/// \param runtime_val Variable which runtime type must be returned. -/// \throw Nothing. -/// \return boost::typeindex::type_index with information about the specified variable. -template -inline type_index type_id_runtime(const T& runtime_val) BOOST_NOEXCEPT { - return type_index::type_id_runtime(runtime_val); -} - -}} // namespace boost::typeindex - - - -#endif // BOOST_TYPE_INDEX_HPP - diff --git a/boost/type_index/ctti_type_index.hpp b/boost/type_index/ctti_type_index.hpp deleted file mode 100644 index 818545b..0000000 --- a/boost/type_index/ctti_type_index.hpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright 2013-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP -#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP - -/// \file ctti_type_index.hpp -/// \brief Contains boost::typeindex::ctti_type_index class that is constexpr if C++14 constexpr is supported by compiler. -/// -/// boost::typeindex::ctti_type_index class can be used as a drop-in replacement -/// for std::type_index. -/// -/// It is used in situations when typeid() method is not available or -/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined. - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost { namespace typeindex { - -namespace detail { - -// That's the most trickiest part of the TypeIndex library: -// 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type` -// 2) we need to distinguish between `struct-that-represents-type` and `const char*` -// 3) we need a thread-safe way to have references to instances `struct-that-represents-type` -// 4) we need a compile-time control to make sure that user does not copy or -// default construct `struct-that-represents-type` -// -// Solution would be the following: - -/// \class ctti_data -/// Standard-layout class with private constructors and assignment operators. -/// -/// You can not work with this class directly. The purpose of this class is to hold type info -/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself. -/// -/// \b Example: -/// \code -/// const detail::ctti_data& foo(); -/// ... -/// type_index ti = type_index(foo()); -/// std::cout << ti.pretty_name(); -/// \endcode -class ctti_data { -#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS -public: - ctti_data() = delete; - ctti_data(const ctti_data&) = delete; - ctti_data& operator=(const ctti_data&) = delete; -#else -private: - ctti_data(); - ctti_data(const ctti_data&); - ctti_data& operator=(const ctti_data&); -#endif -}; - -} // namespace detail - -/// Helper method for getting detail::ctti_data of a template parameter T. -template -inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT { - // Standard C++11, 5.2.10 Reinterpret cast: - // An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue - // v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast(static_cast(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment - // requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type - // "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment - // requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer - // value. - // - // Alignments are checked in `type_index_test_ctti_alignment.cpp` test. - return *reinterpret_cast(boost::detail::ctti::n()); -} - -/// \class ctti_type_index -/// This class is a wrapper that pretends to work exactly like stl_type_index, but does -/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade. -/// -/// This class on C++14 compatible compilers has following functions marked as constexpr: -/// * default constructor -/// * copy constructors and assignemnt operations -/// * class methods: name(), before(const ctti_type_index& rhs), equal(const ctti_type_index& rhs) -/// * static methods type_id(), type_id_with_cvr() -/// * comparison operators -/// -/// This class produces slightly longer type names, so consider using stl_type_index -/// in situations when typeid() is working. -class ctti_type_index: public type_index_facade { - const char* data_; - - inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT; - - BOOST_CXX14_CONSTEXPR inline explicit ctti_type_index(const char* data) BOOST_NOEXCEPT - : data_(data) - {} - -public: - typedef detail::ctti_data type_info_t; - - BOOST_CXX14_CONSTEXPR inline ctti_type_index() BOOST_NOEXCEPT - : data_(boost::detail::ctti::n()) - {} - - inline ctti_type_index(const type_info_t& data) BOOST_NOEXCEPT - : data_(reinterpret_cast(&data)) - {} - - inline const type_info_t& type_info() const BOOST_NOEXCEPT; - BOOST_CXX14_CONSTEXPR inline const char* raw_name() const BOOST_NOEXCEPT; - BOOST_CXX14_CONSTEXPR inline const char* name() const BOOST_NOEXCEPT; - inline std::string pretty_name() const; - inline std::size_t hash_code() const BOOST_NOEXCEPT; - - BOOST_CXX14_CONSTEXPR inline bool equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT; - BOOST_CXX14_CONSTEXPR inline bool before(const ctti_type_index& rhs) const BOOST_NOEXCEPT; - - template - BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id() BOOST_NOEXCEPT; - - template - BOOST_CXX14_CONSTEXPR inline static ctti_type_index type_id_with_cvr() BOOST_NOEXCEPT; - - template - inline static ctti_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT; -}; - - -inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const BOOST_NOEXCEPT { - return *reinterpret_cast(data_); -} - - -BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::equal(const ctti_type_index& rhs) const BOOST_NOEXCEPT { - const char* const left = raw_name(); - const char* const right = rhs.raw_name(); - return /*left == right ||*/ !boost::typeindex::detail::constexpr_strcmp(left, right); -} - -BOOST_CXX14_CONSTEXPR inline bool ctti_type_index::before(const ctti_type_index& rhs) const BOOST_NOEXCEPT { - const char* const left = raw_name(); - const char* const right = rhs.raw_name(); - return /*left != right &&*/ boost::typeindex::detail::constexpr_strcmp(left, right) < 0; -} - - -template -BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id() BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_t; - return ctti_type_index(boost::detail::ctti::n()); -} - - - -template -BOOST_CXX14_CONSTEXPR inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT { - return ctti_type_index(boost::detail::ctti::n()); -} - - -template -inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT { - return variable.boost_type_index_type_id_runtime_(); -} - - -BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT { - return data_; -} - - -BOOST_CXX14_CONSTEXPR inline const char* ctti_type_index::name() const BOOST_NOEXCEPT { - return data_; -} - -inline std::size_t ctti_type_index::get_raw_name_length() const BOOST_NOEXCEPT { - return std::strlen(raw_name() + detail::ctti_skip_size_at_end); -} - - -inline std::string ctti_type_index::pretty_name() const { - std::size_t len = get_raw_name_length(); - while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces - return std::string(raw_name(), len); -} - - -inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT { - return boost::hash_range(raw_name(), raw_name() + get_raw_name_length()); -} - - -}} // namespace boost::typeindex - -#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP - diff --git a/boost/type_index/detail/compile_time_type_info.hpp b/boost/type_index/detail/compile_time_type_info.hpp deleted file mode 100644 index c808084..0000000 --- a/boost/type_index/detail/compile_time_type_info.hpp +++ /dev/null @@ -1,339 +0,0 @@ -// -// Copyright 2012-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP -#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP - -/// \file compile_time_type_info.hpp -/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index. -/// Not intended for inclusion from user's code. - -#include -#include -#include -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -/// @cond -#if defined(__has_builtin) -#if __has_builtin(__builtin_constant_p) -#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) -#endif -#if __has_builtin(__builtin_strcmp) -#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2) -#endif -#elif defined(__GNUC__) -#define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x) -#define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2) -#endif - -#define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until) \ - namespace boost { namespace typeindex { namespace detail { \ - BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin = begin_skip; \ - BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end = end_skip; \ - BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime = runtime_skip; \ - BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[] = runtime_skip_until; \ - }}} /* namespace boost::typeindex::detail */ \ - /**/ -/// @endcond - - -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - /* Nothing to document. All the macro docs are moved to */ -#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING) -# include - BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING ) -#elif defined(_MSC_VER) && !defined(__clang__) && defined (BOOST_NO_CXX11_NOEXCEPT) - // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "") -#elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT) - // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "") -#elif defined(__clang__) && defined(__APPLE__) - // Someone made __clang_major__ equal to LLVM version rather than compiler version - // on APPLE platform. - // - // Using less efficient solution because there is no good way to detect real version of Clang. - // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int" - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ") -#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0)) - // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1 - // note: checked on 3.0 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "") -#elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0)) - // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int" - // note: checked on 3.1, 3.4 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ") -#elif defined(__EDG__) && !defined(BOOST_NO_CXX14_CONSTEXPR) - // sizeof("static cha boost::detail::ctti::s() [with I = 40U, T = ") - 1, sizeof("]") - 1 - // note: checked on 4.14 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(58, 1, false, "") -#elif defined(__EDG__) && defined(BOOST_NO_CXX14_CONSTEXPR) - // sizeof("static const char *boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 - // note: checked on 4.14 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "") -#elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR) - // sizeof("static constexpr char boost::detail::ctti::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "") -#elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR) - // sizeof("static constexpr char boost::detail::ctti::s() [with unsigned int I = 0; T = ") - 1, sizeof("]") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(80, 1, false, "") -#elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR) - // sizeof("static const char* boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "") -#elif defined(__ghs__) - // sizeof("static const char *boost::detail::ctti::n() [with T = ") - 1, sizeof("]") - 1 - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "") -#else - // Deafult code for other platforms... Just skip nothing! - BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "") -#endif - -#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS - -namespace boost { namespace typeindex { namespace detail { - template - BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG( - Condition, - "TypeIndex library is misconfigured for your compiler. " - "Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section " - "'RTTI emulation limitations' of the documentation for more information." - ); - } - - template - BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT { - BOOST_STATIC_ASSERT_MSG( - sizeof(T) && false, - "TypeIndex library could not detect your compiler. " - "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use " - "correct compiler macro for getting the whole function name. " - "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that." - ); - } - -#if defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) - BOOST_CXX14_CONSTEXPR BOOST_FORCEINLINE bool is_constant_string(const char* str) BOOST_NOEXCEPT { - while (BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(*str)) { - if (*str == '\0') - return true; - ++str; - } - return false; - } -#endif // defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) - - template - BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::false_type) BOOST_NOEXCEPT { - return begin; - } - - template - BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search( - ForwardIterator1 first1, - ForwardIterator1 last1, - ForwardIterator2 first2, - ForwardIterator2 last2) BOOST_NOEXCEPT - { - if (first2 == last2) { - return first1; // specified in C++11 - } - - while (first1 != last1) { - ForwardIterator1 it1 = first1; - ForwardIterator2 it2 = first2; - - while (*it1 == *it2) { - ++it1; - ++it2; - if (it2 == last2) return first1; - if (it1 == last1) return last1; - } - - ++first1; - } - - return last1; - } - - BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp_loop(const char *v1, const char *v2) BOOST_NOEXCEPT { - while (*v1 != '\0' && *v1 == *v2) { - ++v1; - ++v2; - } - - return static_cast(*v1) - *v2; - } - - BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT { -#if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) && defined(BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP) - if (boost::typeindex::detail::is_constant_string(v1) && boost::typeindex::detail::is_constant_string(v2)) - return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2); - return BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(v1, v2); -#elif !defined(BOOST_NO_CXX14_CONSTEXPR) - return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2); -#else - return std::strcmp(v1, v2); -#endif - } - - template - BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::true_type) BOOST_NOEXCEPT { - const char* const it = constexpr_search( - begin, begin + ArrayLength, - ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1 - ); - return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1); - } - - template - BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT { - assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>(); - return skip_begining_runtime( - begin + ctti_skip_size_at_begin, - boost::integral_constant() - ); - } - -#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) - template - struct index_seq {}; - - template - struct make_index_sequence_join; - - template - struct make_index_sequence_join, index_seq > { - typedef index_seq type; - }; - - template - struct make_index_seq_impl { - typedef typename make_index_sequence_join< - typename make_index_seq_impl::type, - typename make_index_seq_impl::type - >::type type; - }; - - template - struct make_index_seq_impl { - typedef index_seq<> type; - }; - - template - struct make_index_seq_impl { - typedef index_seq type; - }; - - template - struct cstring { - static constexpr unsigned int size_ = sizeof...(C); - static constexpr char data_[size_] = { C... }; - }; - - template - constexpr char cstring::data_[]; -#endif - -}}} // namespace boost::typeindex::detail - -namespace boost { namespace detail { - -/// Noncopyable type_info that does not require RTTI. -/// CTTI == Compile Time Type Info. -/// This name must be as short as possible, to avoid code bloat -template -struct ctti { - -#if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR) - //helper functions - template - constexpr static char s() BOOST_NOEXCEPT { // step - constexpr unsigned int offset = - (I >= 10u ? 1u : 0u) - + (I >= 100u ? 1u : 0u) - + (I >= 1000u ? 1u : 0u) - + (I >= 10000u ? 1u : 0u) - + (I >= 100000u ? 1u : 0u) - + (I >= 1000000u ? 1u : 0u) - ; - - #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) - return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset]; - #elif defined(__FUNCSIG__) - return __FUNCSIG__[I + offset]; - #else - return __PRETTY_FUNCTION__[I + offset]; - #endif - } - - template - constexpr static const char* impl(::boost::typeindex::detail::index_seq ) BOOST_NOEXCEPT { - return ::boost::typeindex::detail::cstring()...>::data_; - } - - template // `D` means `Dummy` - constexpr static const char* n() BOOST_NOEXCEPT { - #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) - constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); - #elif defined(__FUNCSIG__) - constexpr unsigned int size = sizeof(__FUNCSIG__); - #elif defined(__PRETTY_FUNCTION__) \ - || defined(__GNUC__) \ - || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ - || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ - || (defined(__ICC) && (__ICC >= 600)) \ - || defined(__ghs__) \ - || defined(__DMC__) - constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__); - #else - boost::typeindex::detail::failed_to_get_function_name(); - #endif - - boost::typeindex::detail::assert_compile_time_legths< - (size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1) - >(); - static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported"); - - typedef typename boost::typeindex::detail::make_index_seq_impl< - boost::typeindex::detail::ctti_skip_size_at_begin, - size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin - >::type idx_seq; - return impl(idx_seq()); - } -#else - /// Returns raw name. Must be as short, as possible, to avoid code bloat - BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT { - #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) - return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE); - #elif defined(__FUNCSIG__) - return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__); - #elif defined(__PRETTY_FUNCTION__) \ - || defined(__GNUC__) \ - || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \ - || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \ - || (defined(__ICC) && (__ICC >= 600)) \ - || defined(__ghs__) \ - || defined(__DMC__) \ - || defined(__clang__) - return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__); - #else - boost::typeindex::detail::failed_to_get_function_name(); - return ""; - #endif - } -#endif -}; - -}} // namespace boost::detail - -#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP diff --git a/boost/type_index/detail/ctti_register_class.hpp b/boost/type_index/detail/ctti_register_class.hpp deleted file mode 100644 index ba1f068..0000000 --- a/boost/type_index/detail/ctti_register_class.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2013-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP -#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP - -/// \file ctti_register_class.hpp -/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index. -/// Not intended for inclusion from user's code. - -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost { namespace typeindex { namespace detail { - -template -inline const ctti_data& ctti_construct_typeid_ref(const T*) BOOST_NOEXCEPT { - return ctti_construct(); -} - -}}} // namespace boost::typeindex::detail - -/// @cond -#define BOOST_TYPE_INDEX_REGISTER_CLASS \ - virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \ - return boost::typeindex::detail::ctti_construct_typeid_ref(this); \ - } \ -/**/ -/// @endcond - -#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP - diff --git a/boost/type_index/detail/stl_register_class.hpp b/boost/type_index/detail/stl_register_class.hpp deleted file mode 100644 index 590fc96..0000000 --- a/boost/type_index/detail/stl_register_class.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright 2013-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP -#define BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP - -/// \file stl_register_class.hpp -/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::stl_type_index. -/// Not intended for inclusion from user's code. - -#include - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost { namespace typeindex { namespace detail { - -template -inline const stl_type_index::type_info_t& stl_construct_typeid_ref(const T*) BOOST_NOEXCEPT { - return typeid(T); -} - -}}} // namespace boost::typeindex::detail - -/// @cond -#define BOOST_TYPE_INDEX_REGISTER_CLASS \ - virtual const boost::typeindex::stl_type_index::type_info_t& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \ - return boost::typeindex::detail::stl_construct_typeid_ref(this); \ - } \ -/**/ -/// @endcond - -#endif // BOOST_TYPE_INDEX_STL_REGISTER_CLASS_HPP - diff --git a/boost/type_index/stl_type_index.hpp b/boost/type_index/stl_type_index.hpp deleted file mode 100644 index 06c3cac..0000000 --- a/boost/type_index/stl_type_index.hpp +++ /dev/null @@ -1,278 +0,0 @@ -// -// Copyright 2013-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP -#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP - -/// \file stl_type_index.hpp -/// \brief Contains boost::typeindex::stl_type_index class. -/// -/// boost::typeindex::stl_type_index class can be used as a drop-in replacement -/// for std::type_index. -/// -/// It is used in situations when RTTI is enabled or typeid() method is available. -/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro -/// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index. - -#include - -// MSVC is capable of calling typeid(T) even when RTTI is off -#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC) -#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available." -#endif - -#include -#include // std::strcmp, std::strlen, std::strstr -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if (defined(_MSC_VER) && _MSC_VER > 1600) \ - || (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__)) \ - || (defined(__GNUC__) && __GNUC__ > 4 && __cplusplus >= 201103) -# define BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE -#else -# include -#endif - -#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ - || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) -# include -# include -# include -#endif - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost { namespace typeindex { - -/// \class stl_type_index -/// This class is a wrapper around std::type_info, that workarounds issues and provides -/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade. -/// -/// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index. -class stl_type_index - : public type_index_facade< - stl_type_index, - #ifdef BOOST_NO_STD_TYPEINFO - type_info - #else - std::type_info - #endif - > -{ -public: -#ifdef BOOST_NO_STD_TYPEINFO - typedef type_info type_info_t; -#else - typedef std::type_info type_info_t; -#endif - -private: - const type_info_t* data_; - -public: - inline stl_type_index() BOOST_NOEXCEPT - : data_(&typeid(void)) - {} - - inline stl_type_index(const type_info_t& data) BOOST_NOEXCEPT - : data_(&data) - {} - - inline const type_info_t& type_info() const BOOST_NOEXCEPT; - - inline const char* raw_name() const BOOST_NOEXCEPT; - inline const char* name() const BOOST_NOEXCEPT; - inline std::string pretty_name() const; - - inline std::size_t hash_code() const BOOST_NOEXCEPT; - inline bool equal(const stl_type_index& rhs) const BOOST_NOEXCEPT; - inline bool before(const stl_type_index& rhs) const BOOST_NOEXCEPT; - - template - inline static stl_type_index type_id() BOOST_NOEXCEPT; - - template - inline static stl_type_index type_id_with_cvr() BOOST_NOEXCEPT; - - template - inline static stl_type_index type_id_runtime(const T& value) BOOST_NOEXCEPT; -}; - -inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT { - return *data_; -} - - -inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT { -#ifdef _MSC_VER - return data_->raw_name(); -#else - return data_->name(); -#endif -} - -inline const char* stl_type_index::name() const BOOST_NOEXCEPT { - return data_->name(); -} - -inline std::string stl_type_index::pretty_name() const { - static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<"; - static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1; - - // In case of MSVC demangle() is a no-op, and name() already returns demangled name. - // In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it. - const boost::core::scoped_demangled_name demangled_name(data_->name()); - - const char* begin = demangled_name.get(); - if (!begin) { - boost::throw_exception(std::runtime_error("Type name demangling failed")); - } - - const std::string::size_type len = std::strlen(begin); - const char* end = begin + len; - - if (len > cvr_saver_name_len) { - const char* b = std::strstr(begin, cvr_saver_name); - if (b) { - b += cvr_saver_name_len; - - // Trim leading spaces - while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size - ++ b; - } - - // Skip the closing angle bracket - const char* e = end - 1; - while (e > b && *e != '>') { - -- e; - } - - // Trim trailing spaces - while (e > b && *(e - 1) == ' ') { - -- e; - } - - if (b < e) { - // Parsing seems to have succeeded, the type name is not empty - begin = b; - end = e; - } - } - } - - return std::string(begin, end); -} - - -inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT { -#ifdef BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE - return data_->hash_code(); -#else - return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name())); -#endif -} - - -/// @cond - -// for this compiler at least, cross-shared-library type_info -// comparisons don't work, so we are using typeid(x).name() instead. -# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \ - || defined(_AIX) \ - || (defined(__sgi) && defined(__host_mips)) \ - || (defined(__hpux) && defined(__HP_aCC)) \ - || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) -# define BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES -# endif - -/// @endcond - -inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEPT { -#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES - return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name()); -#else - return !!(*data_ == *rhs.data_); -#endif -} - -inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCEPT { -#ifdef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES - return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0; -#else - return !!data_->before(*rhs.data_); -#endif -} - -#undef BOOST_TYPE_INDEX_CLASSINFO_COMPARE_BY_NAMES - - -template -inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::remove_reference::type no_ref_t; - typedef BOOST_DEDUCED_TYPENAME boost::remove_cv::type no_cvr_prefinal_t; - - # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \ - || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744) - - // Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral' - // in typeid() expressions. Full template specialization for 'integral' fixes that issue: - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_signed::value, - boost::make_signed, - boost::type_identity - >::type no_cvr_prefinal_lazy_t; - - typedef BOOST_DEDUCED_TYPENAME no_cvr_prefinal_t::type no_cvr_t; - #else - typedef no_cvr_prefinal_t no_cvr_t; - #endif - - return typeid(no_cvr_t); -} - -namespace detail { - template class cvr_saver{}; -} - -template -inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT { - typedef BOOST_DEDUCED_TYPENAME boost::conditional< - boost::is_reference::value || boost::is_const::value || boost::is_volatile::value, - detail::cvr_saver, - T - >::type type; - - return typeid(type); -} - - -template -inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT { -#ifdef BOOST_NO_RTTI - return value.boost_type_index_type_id_runtime_(); -#else - return typeid(value); -#endif -} - -}} // namespace boost::typeindex - -#undef BOOST_TYPE_INDEX_STD_TYPE_INDEX_HAS_HASH_CODE - -#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP diff --git a/boost/type_index/type_index_facade.hpp b/boost/type_index/type_index_facade.hpp deleted file mode 100644 index 4145aa4..0000000 --- a/boost/type_index/type_index_facade.hpp +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright 2013-2023 Antony Polukhin. -// -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP -#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP - -#include -#include -#include -#include - -#if !defined(BOOST_NO_IOSTREAM) -#if !defined(BOOST_NO_IOSFWD) -#include // for std::basic_ostream -#else -#include -#endif -#endif - -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -namespace boost { namespace typeindex { - -/// \class type_index_facade -/// -/// This class takes care about the comparison operators, hash functions and -/// ostream operators. Use this class as a public base class for defining new -/// type_info-conforming classes. -/// -/// \b Example: -/// \code -/// class stl_type_index: public type_index_facade -/// { -/// public: -/// typedef std::type_info type_info_t; -/// private: -/// const type_info_t* data_; -/// -/// public: -/// stl_type_index(const type_info_t& data) noexcept -/// : data_(&data) -/// {} -/// // ... -/// }; -/// \endcode -/// -/// \tparam Derived Class derived from type_index_facade. -/// \tparam TypeInfo Class that will be used as a base type_info class. -/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade. -/// Protected member functions raw_name() \b must be defined in Derived class. All the other -/// methods are mandatory. -/// \see 'Making a custom type_index' section for more information about -/// creating your own type_index using type_index_facade. -template -class type_index_facade { -private: - /// @cond - BOOST_CXX14_CONSTEXPR const Derived & derived() const BOOST_NOEXCEPT { - return *static_cast(this); - } - /// @endcond -public: - typedef TypeInfo type_info_t; - - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. - /// \return Name of a type. By default returns Derived::raw_name(). - inline const char* name() const BOOST_NOEXCEPT { - return derived().raw_name(); - } - - /// \b Override: This function \b may be redefined in Derived class. Overrides may throw. - /// \return Human readable type name. By default returns Derived::name(). - inline std::string pretty_name() const { - return derived().name(); - } - - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. - /// \return True if two types are equal. By default compares types by raw_name(). - inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT { - const char* const left = derived().raw_name(); - const char* const right = rhs.raw_name(); - return left == right || !std::strcmp(left, right); - } - - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. - /// \return True if rhs is greater than this. By default compares types by raw_name(). - inline bool before(const Derived& rhs) const BOOST_NOEXCEPT { - const char* const left = derived().raw_name(); - const char* const right = rhs.raw_name(); - return left != right && std::strcmp(left, right) < 0; - } - - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. - /// \return Hash code of a type. By default hashes types by raw_name(). - /// \note Derived class header \b must include , \b unless this function is redefined in - /// Derived class to not use boost::hash_range(). - inline std::size_t hash_code() const BOOST_NOEXCEPT { - const char* const name_raw = derived().raw_name(); - return boost::hash_range(name_raw, name_raw + std::strlen(name_raw)); - } - -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) -protected: - /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw. - /// \return Pointer to unredable/raw type name. - inline const char* raw_name() const BOOST_NOEXCEPT; - - /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw. - /// \return Const reference to underlying low level type_info_t. - inline const type_info_t& type_info() const BOOST_NOEXCEPT; - - /// This is a factory method that is used to create instances of Derived classes. - /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index. - /// - /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. - /// Overrides \b must remove const, volatile && and & modifiers from T. - /// \tparam T Type for which type_index must be created. - /// \return type_index for type T. - template - static Derived type_id() BOOST_NOEXCEPT; - - /// This is a factory method that is used to create instances of Derived classes. - /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index. - /// - /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw. - /// Overrides \b must \b not remove const, volatile && and & modifiers from T. - /// \tparam T Type for which type_index must be created. - /// \return type_index for type T. - template - static Derived type_id_with_cvr() BOOST_NOEXCEPT; - - /// This is a factory method that is used to create instances of Derived classes. - /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index. - /// - /// \b Override: This function \b may be redefined and made public in Derived class. - /// \param variable Variable which runtime type will be stored in type_index. - /// \return type_index with runtime type of variable. - template - static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT; - -#endif - -}; - -/// @cond -template -BOOST_CXX14_CONSTEXPR inline bool operator == (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return static_cast(lhs).equal(static_cast(rhs)); -} - -template -BOOST_CXX14_CONSTEXPR inline bool operator < (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return static_cast(lhs).before(static_cast(rhs)); -} - - - -template -BOOST_CXX14_CONSTEXPR inline bool operator > (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return rhs < lhs; -} - -template -BOOST_CXX14_CONSTEXPR inline bool operator <= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(lhs > rhs); -} - -template -BOOST_CXX14_CONSTEXPR inline bool operator >= (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(lhs < rhs); -} - -template -BOOST_CXX14_CONSTEXPR inline bool operator != (const type_index_facade& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(lhs == rhs); -} - -// ######################### COMPARISONS with Derived ############################ // -template -inline bool operator == (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return Derived(lhs) == rhs; -} - -template -inline bool operator < (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return Derived(lhs) < rhs; -} - -template -inline bool operator > (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return rhs < Derived(lhs); -} - -template -inline bool operator <= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(Derived(lhs) > rhs); -} - -template -inline bool operator >= (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(Derived(lhs) < rhs); -} - -template -inline bool operator != (const TypeInfo& lhs, const type_index_facade& rhs) BOOST_NOEXCEPT { - return !(Derived(lhs) == rhs); -} - - -template -inline bool operator == (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return lhs == Derived(rhs); -} - -template -inline bool operator < (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return lhs < Derived(rhs); -} - -template -inline bool operator > (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return Derived(rhs) < lhs; -} - -template -inline bool operator <= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs > Derived(rhs)); -} - -template -inline bool operator >= (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs < Derived(rhs)); -} - -template -inline bool operator != (const type_index_facade& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT { - return !(lhs == Derived(rhs)); -} - -// ######################### COMPARISONS with Derived END ############################ // - -/// @endcond - -#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED) - -/// noexcept comparison operators for type_index_facade classes. -bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept; - -/// noexcept comparison operators for type_index_facade and it's TypeInfo classes. -bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept; - -/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes. -bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept; - -#endif - -#ifndef BOOST_NO_IOSTREAM -#ifdef BOOST_NO_TEMPLATED_IOSTREAMS -/// @cond -/// Ostream operator that will output demangled name -template -inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade& ind) { - ostr << static_cast(ind).pretty_name(); - return ostr; -} -/// @endcond -#else -/// Ostream operator that will output demangled name. -template -inline std::basic_ostream& operator<<( - std::basic_ostream& ostr, - const type_index_facade& ind) -{ - ostr << static_cast(ind).pretty_name(); - return ostr; -} -#endif // BOOST_NO_TEMPLATED_IOSTREAMS -#endif // BOOST_NO_IOSTREAM - -/// This free function is used by Boost's unordered containers. -/// \note has to be included if this function is used. -template -inline std::size_t hash_value(const type_index_facade& lhs) BOOST_NOEXCEPT { - return static_cast(lhs).hash_code(); -} - -}} // namespace boost::typeindex - -#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP - diff --git a/boost/type_traits/same_traits.hpp b/boost/type_traits/same_traits.hpp deleted file mode 100644 index dab7dac..0000000 --- a/boost/type_traits/same_traits.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). -// -// See http://www.boost.org/libs/type_traits for most recent version including documentation. -// -// defines is_same: - -#ifndef BOOST_TT_SAME_TRAITS_HPP_INCLUDED -#define BOOST_TT_SAME_TRAITS_HPP_INCLUDED - -#include - -#endif // BOOST_TT_SAME_TRAITS_HPP_INCLUDED diff --git a/boost/url.hpp b/boost/url.hpp deleted file mode 100644 index 12f6613..0000000 --- a/boost/url.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/url -// - -#ifndef BOOST_URL_HPP -#define BOOST_URL_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/boost/url/authority_view.hpp b/boost/url/authority_view.hpp index 96b5499..3f8d8a1 100644 --- a/boost/url/authority_view.hpp +++ b/boost/url/authority_view.hpp @@ -31,7 +31,7 @@ namespace urls { strings constructed from a parsed, external character buffer whose storage is managed by the caller. That is, it acts like a - @ref string_view in terms of ownership. + `core::string_view` in terms of ownership. The caller is responsible for ensuring that the lifetime of the underlying character buffer extends until it is no @@ -55,7 +55,7 @@ namespace urls { contain an error. The error can be converted to an exception by the caller if desired: @code - result< authority_view > rv = parse_authority( "user:pass@www.example.com:8080" ); + system::result< authority_view > rv = parse_authority( "user:pass@www.example.com:8080" ); @endcode @par BNF @@ -79,7 +79,7 @@ namespace urls { @see @ref parse_authority. */ -class BOOST_SYMBOL_VISIBLE +class BOOST_URL_DECL authority_view : private detail::parts_base { @@ -103,7 +103,6 @@ public: /** Destructor */ - BOOST_URL_DECL virtual ~authority_view(); @@ -119,7 +118,6 @@ public: @par Specification */ - BOOST_URL_DECL authority_view() noexcept; /** Construct from a string. @@ -157,19 +155,16 @@ public: @see @ref parse_authority. */ - BOOST_URL_DECL explicit - authority_view(string_view s); + authority_view(core::string_view s); /** Constructor */ - BOOST_URL_DECL authority_view( authority_view const&) noexcept; /** Assignment */ - BOOST_URL_DECL authority_view& operator=( authority_view const&) noexcept; @@ -255,10 +250,10 @@ public: @li 3.2. Authority (rfc3986) */ - string_view + core::string_view buffer() const noexcept { - return string_view(data(), size()); + return core::string_view(data(), size()); } //-------------------------------------------- @@ -304,7 +299,6 @@ public: @ref userinfo. */ - BOOST_URL_DECL bool has_userinfo() const noexcept; @@ -399,7 +393,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_userinfo() const noexcept; @@ -498,7 +491,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_user() const noexcept; @@ -540,7 +532,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL bool has_password() const noexcept; @@ -633,7 +624,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_password() const noexcept; @@ -750,7 +740,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host() const noexcept; @@ -865,7 +854,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host_address() const noexcept; @@ -905,7 +893,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL ipv4_address host_ipv4_address() const noexcept; @@ -953,7 +940,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL ipv6_address host_ipv6_address() const noexcept; @@ -986,8 +972,7 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL - string_view + core::string_view host_ipvfuture() const noexcept; /** Return the host name @@ -1069,7 +1054,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host_name() const noexcept; @@ -1111,7 +1095,6 @@ public: @ref port, @ref port_number. */ - BOOST_URL_DECL bool has_port() const noexcept; @@ -1147,8 +1130,7 @@ public: @ref has_port, @ref port_number. */ - BOOST_URL_DECL - string_view + core::string_view port() const noexcept; /** Return the port @@ -1183,7 +1165,6 @@ public: @ref has_port, @ref port. */ - BOOST_URL_DECL std::uint16_t port_number() const noexcept; @@ -1223,7 +1204,6 @@ public: @ref port, @ref port_number. */ - BOOST_URL_DECL pct_string_view encoded_host_and_port() const noexcept; @@ -1249,7 +1229,6 @@ public: @li 6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL int compare(authority_view const& other) const noexcept; @@ -1450,9 +1429,9 @@ operator<<( @ref authority_view. */ BOOST_URL_DECL -result +system::result parse_authority( - string_view s) noexcept; + core::string_view s) noexcept; //------------------------------------------------ diff --git a/boost/url/decode_view.hpp b/boost/url/decode_view.hpp index 373b03d..06372d7 100644 --- a/boost/url/decode_view.hpp +++ b/boost/url/decode_view.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_DECODE_VIEW_HPP #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ make_decode_view( @par Operators The following operators are supported between @ref decode_view and any object that is convertible - to @ref string_view + to `core::string_view` @code bool operator==( decode_view, decode_view ) noexcept; @@ -103,7 +103,7 @@ class decode_view BOOST_URL_DECL explicit decode_view( - string_view s, + core::string_view s, std::size_t n, encoding_opts opt) noexcept; @@ -355,7 +355,7 @@ public: */ BOOST_URL_DECL bool - starts_with( string_view s ) const noexcept; + starts_with( core::string_view s ) const noexcept; /** Checks if the string ends with the given prefix @@ -372,7 +372,7 @@ public: */ BOOST_URL_DECL bool - ends_with( string_view s ) const noexcept; + ends_with( core::string_view s ) const noexcept; /** Checks if the string begins with the given prefix @@ -509,7 +509,7 @@ public: */ BOOST_URL_DECL int - compare(string_view other) const noexcept; + compare(core::string_view other) const noexcept; /** Return the result of comparing to another string @@ -539,17 +539,17 @@ public: private: template using is_match = std::integral_constant::type, decode_view>::value || - std::is_convertible::value) && + std::is_convertible::value) && ( std::is_same::type, decode_view>::value || - std::is_convertible::value) && + std::is_convertible::value) && // not both are convertible to string view ( - !std::is_convertible::value || - !std::is_convertible::value)>; + !std::is_convertible::value || + !std::is_convertible::value)>; static int diff --git a/boost/url/detail/any_params_iter.hpp b/boost/url/detail/any_params_iter.hpp index 0ef1835..0adeec2 100644 --- a/boost/url/detail/any_params_iter.hpp +++ b/boost/url/detail/any_params_iter.hpp @@ -37,8 +37,8 @@ struct BOOST_SYMBOL_VISIBLE protected: any_params_iter( bool empty_, - string_view s0_ = {}, - string_view s1_ = {}) noexcept + core::string_view s0_ = {}, + core::string_view s1_ = {}) noexcept : s0(s0_) , s1(s1_) , empty(empty_) @@ -48,8 +48,8 @@ protected: public: // these are adjusted // when self-intersecting - string_view s0; - string_view s1; + core::string_view s0; + core::string_view s1; // True if the sequence is empty bool empty = false; @@ -97,11 +97,11 @@ struct BOOST_SYMBOL_VISIBLE BOOST_URL_DECL explicit query_iter( - string_view s, + core::string_view s, bool ne = false) noexcept; private: - string_view s_; + core::string_view s_; std::size_t n_; char const* p_; bool at_end_; @@ -124,7 +124,6 @@ struct BOOST_SYMBOL_VISIBLE param_iter : any_params_iter { - BOOST_URL_DECL explicit param_iter( param_view const&) noexcept; @@ -234,7 +233,6 @@ struct BOOST_SYMBOL_VISIBLE param_encoded_iter : any_params_iter { - BOOST_URL_DECL explicit param_encoded_iter( param_pct_view const&) noexcept; @@ -348,7 +346,7 @@ struct param_value_iter { param_value_iter( std::size_t nk, - string_view const& value, + core::string_view const& value, bool has_value) noexcept : any_params_iter( false, diff --git a/boost/url/detail/any_segments_iter.hpp b/boost/url/detail/any_segments_iter.hpp index 129aee9..25cc808 100644 --- a/boost/url/detail/any_segments_iter.hpp +++ b/boost/url/detail/any_segments_iter.hpp @@ -26,7 +26,7 @@ struct BOOST_SYMBOL_VISIBLE protected: explicit any_segments_iter( - string_view s_ = {}) noexcept + core::string_view s_ = {}) noexcept : s(s_) { } @@ -36,11 +36,11 @@ protected: public: // this is adjusted // when self-intersecting - string_view s; + core::string_view s; // the first segment, // to handle special cases - string_view front; + core::string_view front; // quick number of segments // 0 = zero @@ -71,47 +71,6 @@ public: char const* end) noexcept = 0; }; -//------------------------------------------------ - -// iterates segments in a string -struct BOOST_SYMBOL_VISIBLE - path_iter - : any_segments_iter -{ - virtual ~path_iter() = default; - - explicit - path_iter( - string_view s) noexcept; - -protected: - std::size_t pos_; - std::size_t next_; - - void increment() noexcept; - void rewind() noexcept override; - bool measure(std::size_t&) noexcept override; - void copy(char*&, char const*) noexcept override; -}; - -//------------------------------------------------ - -// iterates segments in an encoded string -struct BOOST_SYMBOL_VISIBLE - path_encoded_iter - : public path_iter -{ - virtual ~path_encoded_iter() = default; - - explicit - path_encoded_iter( - pct_string_view s) noexcept; - -private: - bool measure(std::size_t&) noexcept override; - void copy(char*&, char const*) noexcept override; -}; - //------------------------------------------------ // // segment_iter @@ -128,7 +87,7 @@ struct BOOST_SYMBOL_VISIBLE explicit segment_iter( - string_view s) noexcept; + core::string_view s) noexcept; private: bool at_end_ = false; @@ -148,10 +107,10 @@ struct segments_iter_base protected: BOOST_URL_DECL static void measure_impl(std::size_t&, - string_view, bool) noexcept; + core::string_view, bool) noexcept; BOOST_URL_DECL static void copy_impl(char*&, char const*, - string_view, bool) noexcept; + core::string_view, bool) noexcept; }; // iterates segments in a @@ -165,7 +124,7 @@ struct segments_iter std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value); + core::string_view>::value); segments_iter( FwdIt first, @@ -262,10 +221,10 @@ struct segments_encoded_iter_base protected: BOOST_URL_DECL static void measure_impl(std::size_t&, - string_view, bool) noexcept; + core::string_view, bool) noexcept; BOOST_URL_DECL static void copy_impl(char*&, char const*, - string_view, bool) noexcept; + core::string_view, bool) noexcept; }; // iterates segments in an @@ -279,7 +238,7 @@ struct segments_encoded_iter std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value); + core::string_view>::value); segments_encoded_iter( FwdIt first, diff --git a/boost/url/detail/config.hpp b/boost/url/detail/config.hpp index 0f85a59..c298030 100644 --- a/boost/url/detail/config.hpp +++ b/boost/url/detail/config.hpp @@ -20,20 +20,21 @@ # error unsupported platform #endif -#if defined(BOOST_URL_DOCS) -# define BOOST_URL_DECL +// Determine if compiling as a dynamic library +#if (defined(BOOST_URL_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_URL_STATIC_LINK) +# define BOOST_URL_BUILD_DLL +#endif + +// Set visibility flags +#if !defined(BOOST_URL_BUILD_DLL) +# define BOOST_URL_DECL /* static library */ +#elif defined(BOOST_URL_SOURCE) +# define BOOST_URL_DECL BOOST_SYMBOL_EXPORT /* source: dllexport/visibility */ #else -# if (defined(BOOST_URL_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_URL_STATIC_LINK) -# if defined(BOOST_URL_SOURCE) -# define BOOST_URL_DECL BOOST_SYMBOL_EXPORT -# define BOOST_URL_BUILD_DLL -# else -# define BOOST_URL_DECL BOOST_SYMBOL_IMPORT -# endif -# endif // shared lib -# ifndef BOOST_URL_DECL -# define BOOST_URL_DECL -# endif +# define BOOST_URL_DECL BOOST_SYMBOL_IMPORT /* header: dllimport */ +#endif + +// Set up auto-linker # if !defined(BOOST_URL_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_URL_NO_LIB) # define BOOST_LIB_NAME boost_url # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URL_DYN_LINK) @@ -41,8 +42,8 @@ # endif # include # endif -#endif +// Set up SSE2 #if ! defined(BOOST_URL_NO_SSE2) && \ ! defined(BOOST_URL_USE_SSE2) # if (defined(_M_IX86) && _M_IX86_FP == 2) || \ @@ -51,6 +52,7 @@ # endif #endif +// constexpr #if BOOST_WORKAROUND( BOOST_GCC_VERSION, <= 72000 ) || \ BOOST_WORKAROUND( BOOST_CLANG_VERSION, <= 35000 ) # define BOOST_URL_CONSTEXPR @@ -73,6 +75,7 @@ # define BOOST_URL_POS (BOOST_CURRENT_LOCATION) #endif +// String token parameters #ifndef BOOST_URL_STRTOK_TPARAM #define BOOST_URL_STRTOK_TPARAM class StringToken = string_token::return_string #endif @@ -83,6 +86,7 @@ #define BOOST_URL_STRTOK_ARG(name) StringToken&& token = {} #endif +// Move #if BOOST_WORKAROUND( BOOST_GCC_VERSION, < 80000 ) || \ BOOST_WORKAROUND( BOOST_CLANG_VERSION, < 30900 ) #define BOOST_URL_RETURN(x) return std::move((x)) @@ -90,18 +94,21 @@ #define BOOST_URL_RETURN(x) return (x) #endif +// Limit tests #ifndef BOOST_URL_MAX_SIZE // we leave room for a null, // and still fit in size_t #define BOOST_URL_MAX_SIZE ((std::size_t(-1))-1) #endif +// noinline attribute #ifdef BOOST_GCC #define BOOST_URL_NO_INLINE [[gnu::noinline]] #else #define BOOST_URL_NO_INLINE #endif +// libstdcxx copy-on-write strings #ifndef BOOST_URL_COW_STRINGS #if defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 60000 || (defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI == 0)) #define BOOST_URL_COW_STRINGS @@ -117,10 +124,17 @@ # error Unknown or unsupported architecture, please open an issue #endif +// deprecated attribute +#if defined(BOOST_MSVC) || defined(BOOST_URL_DOCS) +#define BOOST_URL_DEPRECATED(msg) +#else +#define BOOST_URL_DEPRECATED(msg) BOOST_DEPRECATED(msg) +#endif + +// avoid Boost.TypeTraits for these traits namespace boost { namespace urls { -// avoid some of Boost.TypeTraits for just this template struct make_void { typedef void type; }; template using void_t = typename make_void::type; diff --git a/boost/url/detail/decode.hpp b/boost/url/detail/decode.hpp index 9ace395..ef08b54 100644 --- a/boost/url/detail/decode.hpp +++ b/boost/url/detail/decode.hpp @@ -12,7 +12,7 @@ #define BOOST_URL_DETAIL_DECODE_HPP #include -#include +#include #include namespace boost { @@ -27,14 +27,14 @@ decode_one( BOOST_URL_DECL std::size_t decode_bytes_unsafe( - string_view s) noexcept; + core::string_view s) noexcept; BOOST_URL_DECL std::size_t decode_unsafe( char* dest, char const* end, - string_view s, + core::string_view s, encoding_opts opt = {}) noexcept; } // detail diff --git a/boost/url/detail/encode.hpp b/boost/url/detail/encode.hpp index ff68a35..a0fc5d0 100644 --- a/boost/url/detail/encode.hpp +++ b/boost/url/detail/encode.hpp @@ -37,7 +37,7 @@ char const* const hexdigs[] = { template std::size_t re_encoded_size_unsafe( - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt) noexcept { @@ -107,7 +107,7 @@ std::size_t re_encode_unsafe( char*& dest_, char const* const end, - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt) noexcept { diff --git a/boost/url/detail/except.hpp b/boost/url/detail/except.hpp index 1462fbc..e354c67 100644 --- a/boost/url/detail/except.hpp +++ b/boost/url/detail/except.hpp @@ -19,13 +19,13 @@ namespace detail { BOOST_URL_DECL void BOOST_NORETURN throw_system_error( - error_code const& ec, + system::error_code const& ec, source_location const& loc = BOOST_URL_POS); BOOST_URL_DECL void BOOST_NORETURN throw_errc( - errc::errc_t ev, + boost::system::errc::errc_t ev, source_location const& loc = BOOST_URL_POS); diff --git a/boost/url/detail/format_args.hpp b/boost/url/detail/format_args.hpp index a863370..0d8416c 100644 --- a/boost/url/detail/format_args.hpp +++ b/boost/url/detail/format_args.hpp @@ -44,7 +44,7 @@ public: constexpr format_parse_context( - string_view fmt, + core::string_view fmt, std::size_t arg_id = 0) : format_parse_context( fmt.data(), @@ -88,10 +88,10 @@ struct ignore_format {}; template struct named_arg { - string_view name; + core::string_view name; T const& value; - named_arg(string_view n, T const& v) + named_arg(core::string_view n, T const& v) : name(n) , value(v) {} @@ -111,7 +111,7 @@ class format_arg format_context&, grammar::lut_chars const&, void const* ); - string_view name_; + core::string_view name_; std::size_t value_ = 0; bool ignore_ = false; @@ -141,7 +141,7 @@ public: format_arg( named_arg&& a ); template - format_arg( string_view name, A&& a ); + format_arg( core::string_view name, A&& a ); format_arg() : format_arg(ignore_format{}) @@ -171,7 +171,7 @@ public: fmt_( pctx, fctx, cs, arg_ ); } - string_view + core::string_view name() const { return name_; @@ -221,7 +221,7 @@ public: } format_arg - get( string_view name ) const noexcept + get( core::string_view name ) const noexcept { for (std::size_t i = 0; i < n_; ++i) { @@ -259,7 +259,7 @@ public: } format_arg - arg( string_view name ) const noexcept + arg( core::string_view name ) const noexcept { return args_.get( name ); } @@ -309,7 +309,7 @@ public: } format_arg - arg( string_view name ) const noexcept + arg( core::string_view name ) const noexcept { return args_.get( name ); } diff --git a/boost/url/detail/impl/format_args.hpp b/boost/url/detail/impl/format_args.hpp index eb92853..4ce26db 100644 --- a/boost/url/detail/impl/format_args.hpp +++ b/boost/url/detail/impl/format_args.hpp @@ -58,7 +58,7 @@ get_uvalue( A&& a ) BOOST_URL_DECL std::size_t -get_uvalue( string_view a ); +get_uvalue( core::string_view a ); BOOST_URL_DECL std::size_t @@ -86,7 +86,7 @@ format_arg( named_arg&& a ) template format_arg:: -format_arg( string_view name, A&& a ) +format_arg( core::string_view name, A&& a ) : arg_( &a ) , measure_( &measure_impl ) , fmt_( &format_impl ) @@ -219,20 +219,20 @@ BOOST_URL_DECL void get_width_from_args( std::size_t arg_idx, - string_view arg_name, + core::string_view arg_name, format_args args, std::size_t& w); // formatter for string view template <> -struct formatter +struct formatter { private: char fill = ' '; char align = '\0'; std::size_t width = 0; std::size_t width_idx = std::size_t(-1); - string_view width_name; + core::string_view width_name; public: BOOST_URL_DECL @@ -242,14 +242,14 @@ public: BOOST_URL_DECL std::size_t measure( - string_view str, + core::string_view str, measure_context& ctx, grammar::lut_chars const& cs) const; BOOST_URL_DECL char* format( - string_view str, + core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const; }; @@ -260,9 +260,9 @@ template struct formatter< T, typename std::enable_if< std::is_convertible< - T, string_view>::value>::type> + T, core::string_view>::value>::type> { - formatter impl_; + formatter impl_; public: char const* @@ -273,7 +273,7 @@ public: std::size_t measure( - string_view str, + core::string_view str, measure_context& ctx, grammar::lut_chars const& cs) const { @@ -281,7 +281,7 @@ public: } char* - format(string_view str, format_context& ctx, grammar::lut_chars const& cs) const + format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const { return impl_.format(str, ctx, cs); } @@ -290,7 +290,7 @@ public: template <> struct formatter { - formatter impl_; + formatter impl_; public: char const* @@ -327,7 +327,7 @@ class integer_formatter_impl bool zeros = false; std::size_t width = 0; std::size_t width_idx = std::size_t(-1); - string_view width_name; + core::string_view width_name; public: BOOST_URL_DECL diff --git a/boost/url/detail/impl/path.ipp b/boost/url/detail/impl/path.ipp deleted file mode 100644 index 916bfa7..0000000 --- a/boost/url/detail/impl/path.ipp +++ /dev/null @@ -1,23 +0,0 @@ -// -// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/url -// - -#ifndef BOOST_URL_DETAIL_IMPL_PATH_IPP -#define BOOST_URL_DETAIL_IMPL_PATH_IPP - -#include - -namespace boost { -namespace urls { -namespace detail { - -} // detail -} // url -} // boost - -#endif \ No newline at end of file diff --git a/boost/url/detail/move_chars.hpp b/boost/url/detail/move_chars.hpp index a1e9bb0..7af4f4b 100644 --- a/boost/url/detail/move_chars.hpp +++ b/boost/url/detail/move_chars.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_URL_DETAIL_MOVE_CHARS_HPP #define BOOST_URL_DETAIL_MOVE_CHARS_HPP -#include +#include #include #include #include @@ -26,8 +26,8 @@ namespace detail { inline bool is_overlapping( - string_view buf, - string_view s) noexcept + core::string_view buf, + core::string_view s) noexcept { auto const b0 = buf.data(); auto const e0 = b0 + buf.size(); @@ -49,7 +49,7 @@ inline void move_chars_impl( std::ptrdiff_t, - string_view const&) noexcept + core::string_view const&) noexcept { } @@ -57,8 +57,8 @@ template void move_chars_impl( std::ptrdiff_t d, - string_view const& buf, - string_view& s, + core::string_view const& buf, + core::string_view& s, Sn&... sn) noexcept { if(is_overlapping(buf, s)) @@ -74,10 +74,10 @@ move_chars( std::size_t n, Args&... args) noexcept { - string_view buf(src, n); + core::string_view buf(src, n); move_chars_impl( dest - src, - string_view(src, n), + core::string_view(src, n), args...); std::memmove( dest, src, n); diff --git a/boost/url/detail/normalize.hpp b/boost/url/detail/normalize.hpp index caf0474..dc11178 100644 --- a/boost/url/detail/normalize.hpp +++ b/boost/url/detail/normalize.hpp @@ -11,7 +11,9 @@ #ifndef BOOST_URL_DETAIL_NORMALIZED_HPP #define BOOST_URL_DETAIL_NORMALIZED_HPP -#include +#include +#include +#include namespace boost { namespace urls { @@ -48,7 +50,7 @@ public: } void - put(string_view s) noexcept + put(core::string_view s) noexcept { for (char c: s) { @@ -68,78 +70,78 @@ private: void pop_encoded_front( - string_view& s, + core::string_view& s, char& c, std::size_t& n) noexcept; -// compare two string_views as if they are both +// compare two core::string_views as if they are both // percent-decoded int compare_encoded( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// digest a string_view as if it were +// digest a core::string_view as if it were // percent-decoded void digest_encoded( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept; void digest( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept; -// check if string_view lhs starts with string_view +// check if core::string_view lhs starts with core::string_view // rhs as if they are both percent-decoded. If // lhs starts with rhs, return number of chars -// matched in the encoded string_view +// matched in the encoded core::string_view std::size_t path_starts_with( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// check if string_view lhs ends with string_view +// check if core::string_view lhs ends with core::string_view // rhs as if they are both percent-decoded. If // lhs ends with rhs, return number of chars -// matched in the encoded string_view +// matched in the encoded core::string_view std::size_t path_ends_with( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// compare two string_views as if they are both +// compare two core::string_views as if they are both // percent-decoded and lowercase int ci_compare_encoded( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// digest a string_view as if it were decoded +// digest a core::string_view as if it were decoded // and lowercase void ci_digest_encoded( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept; -// compare two ascii string_views +// compare two ascii core::string_views int compare( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// compare two string_views as if they are both +// compare two core::string_views as if they are both // lowercase int ci_compare( - string_view lhs, - string_view rhs) noexcept; + core::string_view lhs, + core::string_view rhs) noexcept; -// digest a string_view as if it were lowercase +// digest a core::string_view as if it were lowercase void ci_digest( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept; BOOST_URL_DECL @@ -147,21 +149,21 @@ std::size_t remove_dot_segments( char* dest, char const* end, - string_view s) noexcept; + core::string_view s) noexcept; void pop_last_segment( - string_view& s, - string_view& c, + core::string_view& s, + core::string_view& c, std::size_t& level, bool r) noexcept; char -path_pop_back( string_view& s ); +path_pop_back( core::string_view& s ); void normalized_path_digest( - string_view s, + core::string_view s, bool remove_unmatched, fnv_1a& hasher) noexcept; diff --git a/boost/url/detail/optional_string.hpp b/boost/url/detail/optional_string.hpp index 7c93409..97a685b 100644 --- a/boost/url/detail/optional_string.hpp +++ b/boost/url/detail/optional_string.hpp @@ -10,7 +10,8 @@ #ifndef BOOST_URL_DETAIL_OPTIONAL_STRING_HPP #define BOOST_URL_DETAIL_OPTIONAL_STRING_HPP -#include +#include +#include namespace boost { namespace urls { @@ -22,13 +23,13 @@ struct no_value_t; namespace detail { struct optional_string { - string_view s; + core::string_view s; bool b = false; }; template typename std::enable_if< - std::is_convertible::value, + std::is_convertible::value, optional_string>::type get_optional_string( String const& s) @@ -53,7 +54,7 @@ struct is_dereferenceable< template typename std::enable_if< - !std::is_convertible::value, + !std::is_convertible::value, optional_string>::type get_optional_string( OptionalString const& opt) @@ -65,11 +66,11 @@ get_optional_string( static_assert( is_dereferenceable::value && std::is_constructible::value && - !std::is_convertible::value && - std::is_convertible())>::type, string_view>::value, + !std::is_convertible::value && + std::is_convertible())>::type, core::string_view>::value, "OptionalString requirements not met"); optional_string r; - r.s = opt ? detail::to_sv(*opt) : string_view{}; + r.s = opt ? detail::to_sv(*opt) : core::string_view{}; r.b = static_cast(opt); return r; } diff --git a/boost/url/detail/params_iter_impl.hpp b/boost/url/detail/params_iter_impl.hpp index 2492528..b2a268e 100644 --- a/boost/url/detail/params_iter_impl.hpp +++ b/boost/url/detail/params_iter_impl.hpp @@ -19,7 +19,7 @@ namespace boost { namespace urls { namespace detail { -struct params_iter_impl +struct BOOST_URL_DECL params_iter_impl : parts_base { query_ref ref; @@ -37,12 +37,10 @@ struct params_iter_impl params_iter_impl const&) = default; // begin - BOOST_URL_DECL params_iter_impl( query_ref const&) noexcept; // end - BOOST_URL_DECL params_iter_impl( query_ref const&, int) noexcept; @@ -53,9 +51,9 @@ struct params_iter_impl std::size_t, std::size_t) noexcept; void setup() noexcept; - BOOST_URL_DECL void increment() noexcept; - BOOST_URL_DECL void decrement() noexcept; - BOOST_URL_DECL param_pct_view + void increment() noexcept; + void decrement() noexcept; + param_pct_view dereference() const noexcept; pct_string_view key() const noexcept; diff --git a/boost/url/detail/path.hpp b/boost/url/detail/path.hpp index d7f0aae..d4c3682 100644 --- a/boost/url/detail/path.hpp +++ b/boost/url/detail/path.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_URL_DETAIL_PATH_HPP #define BOOST_URL_DETAIL_PATH_HPP -#include +#include namespace boost { namespace urls { @@ -62,7 +62,7 @@ path_prefix( inline std::size_t path_prefix( - string_view s) noexcept + core::string_view s) noexcept { return path_prefix( s.data(), s.size()); @@ -73,7 +73,7 @@ path_prefix( inline std::size_t path_segments( - string_view s, + core::string_view s, std::size_t nseg) noexcept { switch(s.size()) @@ -124,9 +124,9 @@ path_segments( // Trim reserved characters from // the front of the path. inline -string_view +core::string_view clean_path( - string_view s) noexcept + core::string_view s) noexcept { s.remove_prefix( path_prefix(s)); diff --git a/boost/url/detail/pattern.hpp b/boost/url/detail/pattern.hpp index be6c31d..931d2dd 100644 --- a/boost/url/detail/pattern.hpp +++ b/boost/url/detail/pattern.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include // This file includes functions and classes // to parse uri templates or format strings @@ -25,14 +25,14 @@ class format_args; struct pattern { - string_view scheme; - string_view user; - string_view pass; - string_view host; - string_view port; - string_view path; - string_view query; - string_view frag; + core::string_view scheme; + core::string_view user; + core::string_view pass; + core::string_view host; + core::string_view port; + core::string_view path; + core::string_view query; + core::string_view frag; bool has_authority = false; bool has_user = false; @@ -49,9 +49,9 @@ struct pattern }; BOOST_URL_DECL -result +system::result parse_pattern( - string_view s); + core::string_view s); } // detail } // url diff --git a/boost/url/detail/pct_format.hpp b/boost/url/detail/pct_format.hpp index 06b924f..0d13b3f 100644 --- a/boost/url/detail/pct_format.hpp +++ b/boost/url/detail/pct_format.hpp @@ -10,7 +10,7 @@ #ifndef BOOST_URL_DETAIL_PCT_FORMAT_HPP #define BOOST_URL_DETAIL_PCT_FORMAT_HPP -#include +#include #include #include #include diff --git a/boost/url/detail/print.hpp b/boost/url/detail/print.hpp index 89a0782..dffc5ab 100644 --- a/boost/url/detail/print.hpp +++ b/boost/url/detail/print.hpp @@ -10,10 +10,6 @@ #ifndef BOOST_URL_DETAIL_PRINT_HPP #define BOOST_URL_DETAIL_PRINT_HPP -#ifndef BOOST_URL_SOURCE -#error -#endif - #include #include @@ -61,10 +57,10 @@ public: } } - string_view + core::string_view string() const noexcept { - return string_view(buf_ + + return core::string_view(buf_ + sizeof(buf_) - n_, n_); } }; diff --git a/boost/url/detail/replacement_field_rule.hpp b/boost/url/detail/replacement_field_rule.hpp index f6b5de5..a3ce50c 100644 --- a/boost/url/detail/replacement_field_rule.hpp +++ b/boost/url/detail/replacement_field_rule.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_DETAIL_REPLACEMENT_FIELD_RULE_HPP #include -#include +#include #include #include @@ -22,10 +22,10 @@ namespace detail { // replacement_field ::= "{" [arg_id] [":" format_spec "}" struct replacement_field_rule_t { - using value_type = string_view; + using value_type = core::string_view; BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end) const noexcept; @@ -38,10 +38,10 @@ constexpr replacement_field_rule_t replacement_field_rule{}; // id_continue ::= id_start | digit struct identifier_rule_t { - using value_type = string_view; + using value_type = core::string_view; BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end) const noexcept; @@ -59,9 +59,9 @@ static constexpr auto arg_id_rule = struct format_spec_rule_t { - using value_type = string_view; + using value_type = core::string_view; - result + system::result parse( char const*& it, char const* end) const noexcept; diff --git a/boost/url/detail/segments_iter_impl.hpp b/boost/url/detail/segments_iter_impl.hpp index 9edfd7b..c412e64 100644 --- a/boost/url/detail/segments_iter_impl.hpp +++ b/boost/url/detail/segments_iter_impl.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include namespace boost { diff --git a/boost/url/detail/string_view.hpp b/boost/url/detail/string_view.hpp index 12eea19..2fe20ae 100644 --- a/boost/url/detail/string_view.hpp +++ b/boost/url/detail/string_view.hpp @@ -16,15 +16,15 @@ namespace boost { namespace urls { namespace detail { -// We use detail::to_sv(s) instead of string_view(s) whenever -// we should convert to string_view. +// We use detail::to_sv(s) instead of core::string_view(s) whenever +// we should convert to core::string_view. // This is a workaround for GCC >=8.0 <8.4 // See: https://github.com/boostorg/url/issues/672 template core::string_view to_sv(T const& t) noexcept { - return boost::core::string_view(t); + return core::string_view(t); } } // detail diff --git a/boost/url/detail/url_impl.hpp b/boost/url/detail/url_impl.hpp index b011c3a..ca600d5 100644 --- a/boost/url/detail/url_impl.hpp +++ b/boost/url/detail/url_impl.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,7 +31,7 @@ constexpr char const* const empty_c_str_ = ""; // This is the private 'guts' of a // url_view, exposed so different parts // of the implementation can work on it. -struct url_impl : parts_base +struct BOOST_URL_DECL url_impl : parts_base { static constexpr @@ -70,8 +70,8 @@ struct url_impl : parts_base std::size_t len(int, int) const noexcept; std::size_t len(int) const noexcept; std::size_t offset(int) const noexcept; - string_view get(int) const noexcept; - string_view get(int, int) const noexcept; + core::string_view get(int) const noexcept; + core::string_view get(int, int) const noexcept; pct_string_view pct_get(int) const noexcept; pct_string_view pct_get(int, int) const noexcept; void set_size(int, std::size_t) noexcept; @@ -79,12 +79,12 @@ struct url_impl : parts_base void adjust(int, int, std::size_t) noexcept; void collapse(int, int, std::size_t) noexcept; - void apply_scheme(string_view) noexcept; + void apply_scheme(core::string_view) noexcept; void apply_userinfo(pct_string_view const&, pct_string_view const*) noexcept; void apply_host(host_type, pct_string_view, unsigned char const*) noexcept; - void apply_port(string_view, unsigned short) noexcept; + void apply_port(core::string_view, unsigned short) noexcept; void apply_authority(authority_view const&) noexcept; void apply_path(pct_string_view, std::size_t) noexcept; void apply_query(pct_string_view, std::size_t) noexcept; @@ -94,7 +94,7 @@ struct url_impl : parts_base //------------------------------------------------ // this allows a path to come from a -// url_impl or a separate string_view +// url_impl or a separate core::string_view class path_ref : private parts_base { @@ -107,7 +107,7 @@ class path_ref public: path_ref() = default; path_ref(url_impl const& impl) noexcept; - path_ref(string_view, + path_ref(core::string_view, std::size_t, std::size_t) noexcept; pct_string_view buffer() const noexcept; std::size_t size() const noexcept; @@ -139,8 +139,8 @@ public: //------------------------------------------------ // this allows a params to come from a -// url_impl or a separate string_view -class query_ref +// url_impl or a separate core::string_view +class BOOST_URL_DECL query_ref : private parts_base { url_impl const* impl_ = nullptr; @@ -152,12 +152,11 @@ class query_ref public: query_ref( - string_view s, // buffer, no '?' + core::string_view s, // buffer, no '?' std::size_t dn, // decoded size std::size_t nparam ) noexcept; query_ref() = default; - BOOST_URL_DECL query_ref(url_impl const& impl) noexcept; pct_string_view buffer() const noexcept; std::size_t size() const noexcept; // with '?' @@ -186,158 +185,6 @@ public: } }; -//------------------------------------------------ - -// return length of [first, last) -inline -auto -url_impl:: -len( - int first, - int last) const noexcept -> - std::size_t -{ - BOOST_ASSERT(first <= last); - BOOST_ASSERT(last <= id_end); - return offset(last) - offset(first); -} - -// return length of part -inline -auto -url_impl:: -len(int id) const noexcept -> - std::size_t -{ - return id == id_end - ? zero_ - : ( offset(id + 1) - - offset(id) ); -} - -// return offset of id -inline -auto -url_impl:: -offset(int id) const noexcept -> - std::size_t -{ - return - id == id_scheme - ? zero_ - : offset_[id]; -} - -// return id as string -inline -string_view -url_impl:: -get(int id) const noexcept -{ - return { - cs_ + offset(id), len(id) }; -} - -// return [first, last) as string -inline -string_view -url_impl:: -get(int first, - int last) const noexcept -{ - return { cs_ + offset(first), - offset(last) - offset(first) }; -} - -// return id as pct-string -inline -pct_string_view -url_impl:: -pct_get( - int id) const noexcept -{ - return make_pct_string_view_unsafe( - cs_ + offset(id), - len(id), - decoded_[id]); -} - -// return [first, last) as pct-string -inline -pct_string_view -url_impl:: -pct_get( - int first, - int last) const noexcept -{ - auto const pos = offset(first); - std::size_t n = 0; - for(auto i = first; i < last;) - n += decoded_[i++]; - return make_pct_string_view_unsafe( - cs_ + pos, - offset(last) - pos, - n); -} - -//------------------------------------------------ - -// change id to size n -inline -void -url_impl:: -set_size( - int id, - std::size_t n) noexcept -{ - auto d = n - len(id); - for(auto i = id + 1; - i <= id_end; ++i) - offset_[i] += d; -} - -// trim id to size n, -// moving excess into id+1 -inline -void -url_impl:: -split( - int id, - std::size_t n) noexcept -{ - BOOST_ASSERT(id < id_end - 1); - //BOOST_ASSERT(n <= len(id)); - offset_[id + 1] = offset(id) + n; -} - -// add n to [first, last] -inline -void -url_impl:: -adjust( - int first, - int last, - std::size_t n) noexcept -{ - for(int i = first; - i <= last; ++i) - offset_[i] += n; -} - -// set [first, last) offset -inline -void -url_impl:: -collapse( - int first, - int last, - std::size_t n) noexcept -{ - for(int i = first + 1; - i < last; ++i) - offset_[i] = n; -} - } // detail } // urls diff --git a/boost/url/detail/vformat.hpp b/boost/url/detail/vformat.hpp index 4332fe0..126d321 100644 --- a/boost/url/detail/vformat.hpp +++ b/boost/url/detail/vformat.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -23,7 +23,7 @@ inline void vformat_to( url_base& u, - string_view fmt, + core::string_view fmt, detail::format_args args) { parse_pattern(fmt) @@ -33,7 +33,7 @@ vformat_to( inline url vformat( - string_view fmt, + core::string_view fmt, detail::format_args args) { url u; diff --git a/boost/url/encode.hpp b/boost/url/encode.hpp index 26cab7e..c7d1496 100644 --- a/boost/url/encode.hpp +++ b/boost/url/encode.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -61,7 +61,7 @@ namespace urls { template std::size_t encoded_size( - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt = {}) noexcept; @@ -119,7 +119,7 @@ std::size_t encode( char* dest, std::size_t size, - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt = {}); @@ -130,7 +130,7 @@ std::size_t encode_unsafe( char* dest, std::size_t size, - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt); #endif @@ -183,7 +183,7 @@ template< class CharSet> BOOST_URL_STRTOK_RETURN encode( - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt = {}, BOOST_URL_STRTOK_ARG(token)) noexcept; diff --git a/boost/url/encoding_opts.hpp b/boost/url/encoding_opts.hpp index 33bd8a1..d78633b 100644 --- a/boost/url/encoding_opts.hpp +++ b/boost/url/encoding_opts.hpp @@ -28,7 +28,7 @@ namespace urls { @ref encoded_size, @ref pct_string_view. */ -struct encoding_opts +struct BOOST_URL_DECL encoding_opts { /** True if spaces encode to and from plus signs @@ -71,11 +71,7 @@ struct encoding_opts encoding_opts( bool space_as_plus_ = false, bool lower_case_ = false, - bool disallow_null_ = false) noexcept - : space_as_plus(space_as_plus_) - , lower_case(lower_case_) - , disallow_null(disallow_null_) - {} + bool disallow_null_ = false) noexcept; #endif }; diff --git a/boost/url/error_types.hpp b/boost/url/error_types.hpp index f48a2bd..10a31a1 100644 --- a/boost/url/error_types.hpp +++ b/boost/url/error_types.hpp @@ -22,34 +22,161 @@ namespace urls { namespace error_types { #endif -/// The type of error category used by the library -using error_category = boost::system::error_category; +/** The type of error category used by the library -/// The type of error code used by the library -using error_code = boost::system::error_code; + @note This alias is no longer supported and + should not be used in new code. Please use + `system::error_category` instead. -/// The type of error condition used by the library -using error_condition = boost::system::error_condition; + This alias is included for backwards + compatibility with earlier versions of the + library. -/// The type of system error thrown by the library -using system_error = boost::system::system_error; + However, it will be removed in future releases, + and using it in new code is not recommended. -/// A function to return the generic error category used by the library + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +using error_category + BOOST_URL_DEPRECATED("Use system::error_category instead") = + boost::system::error_category; + +/** The type of error code used by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `system::error_code` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +using error_code + BOOST_URL_DEPRECATED("Use system::error_code instead") = + boost::system::error_code; + +/** The type of error condition used by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `system::error_condition` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +using error_condition + BOOST_URL_DEPRECATED("Use system::error_condition instead") = + boost::system::error_condition; + +/** The type of system error thrown by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `system::system_error` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +using system_error + BOOST_URL_DEPRECATED("Use system::system_error instead") = + boost::system::system_error; + +/** A function to return the generic error category used by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `core::string_view` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ #ifdef BOOST_URL_DOCS error_category const& generic_category(); #else using boost::system::generic_category; #endif -/// A function to return the system error category used by the library -#if BOOST_URL_DOCS +/** A function to return the system error category used by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `core::string_view` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +#ifdef BOOST_URL_DOCS error_category const& system_category(); #else using boost::system::system_category; #endif -/// The set of constants used for cross-platform error codes -#if BOOST_URL_DOCS +/** The set of constants used for cross-platform error codes + + @note This alias is no longer supported and + should not be used in new code. Please use + `core::string_view` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + */ +#ifdef BOOST_URL_DOCS enum errc { __see_below__ @@ -60,7 +187,22 @@ namespace errc = boost::system::errc; /** The type of result returned by library functions - This is an alias template used as the return type + @note This alias is no longer supported and + should not be used in new code. Please use + `system::result` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + + @details This is an alias template used as the return type for functions that can either return a container, or fail with an error code. This is a brief synopsis of the type: @@ -79,7 +221,7 @@ namespace errc = boost::system::errc; // // Return the error // - constexpr error_code error() const noexcept; + constexpr system::error_code error() const noexcept; // // Return true if the result contains a value @@ -107,7 +249,7 @@ namespace errc = boost::system::errc; @par Usage Given the function @ref parse_uri with this signature: @code - result< url_view > parse_uri( string_view s ) noexcept; + system::result< url_view > parse_uri( core::string_view s ) noexcept; @endcode The following statement captures the value in a @@ -119,7 +261,7 @@ namespace errc = boost::system::errc; This statement captures the result in a local variable and inspects the error condition: @code - result< url_view > rv = parse_uri( "http://example.com/path/to/file.txt" ); + system::result< url_view > rv = parse_uri( "http://example.com/path/to/file.txt" ); if(! rv ) std::cout << rv.error(); @@ -135,7 +277,9 @@ namespace errc = boost::system::errc; */ template -using result = boost::system::result; +using result + BOOST_URL_DEPRECATED("Use system::result instead") = + boost::system::result; #ifndef BOOST_URL_DOCS } // error_types diff --git a/boost/url/format.hpp b/boost/url/format.hpp index 3e84b12..58042a9 100644 --- a/boost/url/format.hpp +++ b/boost/url/format.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_FORMAT_HPP #include -#include +#include #include #include #include @@ -90,7 +90,7 @@ namespace urls { template url format( - string_view fmt, + core::string_view fmt, Args&&... args) { return detail::vformat( @@ -174,7 +174,7 @@ template void format_to( url_base& u, - string_view fmt, + core::string_view fmt, Args&&... args) { detail::vformat_to( @@ -262,7 +262,7 @@ format_to( inline url format( - string_view fmt, + core::string_view fmt, #ifdef BOOST_URL_DOCS std::initializer_list<__see_below__> args #else @@ -360,7 +360,7 @@ inline void format_to( url_base& u, - string_view fmt, + core::string_view fmt, #ifdef BOOST_URL_DOCS std::initializer_list<__see_below__> args #else @@ -405,7 +405,7 @@ __implementation_defined__ #else detail::named_arg #endif -arg(string_view name, T const& arg) +arg(core::string_view name, T const& arg) { return {name, arg}; } diff --git a/boost/url/grammar/all_chars.hpp b/boost/url/grammar/all_chars.hpp index dc66789..97946d2 100644 --- a/boost/url/grammar/all_chars.hpp +++ b/boost/url/grammar/all_chars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > rv = parse( "JohnDoe", token_rule( all_chars ) ); + system::result< core::string_view > rv = parse( "JohnDoe", token_rule( all_chars ) ); @endcode @par BNF diff --git a/boost/url/grammar/alnum_chars.hpp b/boost/url/grammar/alnum_chars.hpp index bd6cb96..a7d4ef9 100644 --- a/boost/url/grammar/alnum_chars.hpp +++ b/boost/url/grammar/alnum_chars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > = parse( "Johnny42", token_rule( alnumchars ) ); + system::result< core::string_view > = parse( "Johnny42", token_rule( alnumchars ) ); @endcode @par BNF diff --git a/boost/url/grammar/alpha_chars.hpp b/boost/url/grammar/alpha_chars.hpp index 51dd83a..88e2ab5 100644 --- a/boost/url/grammar/alpha_chars.hpp +++ b/boost/url/grammar/alpha_chars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > rv = parse( "JohnDoe", token_rule( alpha_chars ) ); + system::result< core::string_view > rv = parse( "JohnDoe", token_rule( alpha_chars ) ); @endcode @par BNF diff --git a/boost/url/grammar/ci_string.hpp b/boost/url/grammar/ci_string.hpp index f8967ed..1899d34 100644 --- a/boost/url/grammar/ci_string.hpp +++ b/boost/url/grammar/ci_string.hpp @@ -12,7 +12,7 @@ #define BOOST_URL_GRAMMAR_CI_STRING_HPP #include -#include +#include #include #include @@ -119,8 +119,8 @@ to_upper(char c) noexcept BOOST_URL_DECL int ci_compare( - string_view s0, - string_view s1) noexcept; + core::string_view s0, + core::string_view s1) noexcept; /** Return the case-insensitive digest of a string @@ -139,7 +139,7 @@ ci_compare( BOOST_URL_DECL std::size_t ci_digest( - string_view s) noexcept; + core::string_view s) noexcept; //------------------------------------------------ @@ -176,13 +176,13 @@ ci_is_equal( String1 const& s1) -> typename std::enable_if< ! std::is_convertible< - String0, string_view>::value || + String0, core::string_view>::value || ! std::is_convertible< - String1, string_view>::value, + String1, core::string_view>::value, bool>::type { // this overload supports forward iterators and - // does not assume the existence string_view::size + // does not assume the existence core::string_view::size if( detail::type_id() > detail::type_id()) return detail::ci_is_equal(s1, s0); @@ -192,11 +192,11 @@ ci_is_equal( inline bool ci_is_equal( - string_view s0, - string_view s1) noexcept + core::string_view s0, + core::string_view s1) noexcept { // this overload is faster as it makes use of - // string_view::size + // core::string_view::size if(s0.size() != s1.size()) return false; return detail::ci_is_equal(s0, s1); @@ -224,8 +224,8 @@ ci_is_equal( inline bool ci_is_less( - string_view s0, - string_view s1) noexcept + core::string_view s0, + core::string_view s1) noexcept { if(s0.size() != s1.size()) return s0.size() < s1.size(); @@ -264,7 +264,7 @@ struct ci_hash std::size_t operator()( - string_view s) const noexcept + core::string_view s) const noexcept { return ci_digest(s); } @@ -341,8 +341,8 @@ struct ci_less std::size_t operator()( - string_view s0, - string_view s1) const noexcept + core::string_view s0, + core::string_view s1) const noexcept { return ci_is_less(s0, s1); } diff --git a/boost/url/grammar/dec_octet_rule.hpp b/boost/url/grammar/dec_octet_rule.hpp index d32ab46..955652c 100644 --- a/boost/url/grammar/dec_octet_rule.hpp +++ b/boost/url/grammar/dec_octet_rule.hpp @@ -31,7 +31,7 @@ namespace grammar { @par Example Rules are used with the function @ref parse. @code - result< unsigned char > rv = parse( "255", dec_octet_rule ); + system::result< unsigned char > rv = parse( "255", dec_octet_rule ); @endcode @par BNF @@ -63,7 +63,7 @@ struct dec_octet_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr dec_octet_rule_t dec_octet_rule{}; diff --git a/boost/url/grammar/delim_rule.hpp b/boost/url/grammar/delim_rule.hpp index 2493d6b..be71d32 100644 --- a/boost/url/grammar/delim_rule.hpp +++ b/boost/url/grammar/delim_rule.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_GRAMMAR_DELIM_RULE_HPP #include -#include +#include #include #include #include @@ -26,20 +26,20 @@ namespace grammar { This matches the specified character. The value is a reference to the character in the underlying buffer, expressed as a - @ref string_view. The function @ref squelch + `core::string_view`. The function @ref squelch may be used to turn this into `void` instead. If there is no more input, the error code @ref error::need_more is returned. @par Value Type @code - using value_type = string_view; + using value_type = core::string_view; @endcode @par Example Rules are used with the function @ref parse. @code - result< string_view > rv = parse( ".", delim_rule('.') ); + system::result< core::string_view > rv = parse( ".", delim_rule('.') ); @endcode @par BNF @@ -60,7 +60,7 @@ delim_rule( char ch ) noexcept; #else struct ch_delim_rule { - using value_type = string_view; + using value_type = core::string_view; constexpr ch_delim_rule(char ch) noexcept @@ -69,7 +69,7 @@ struct ch_delim_rule } BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end) const noexcept; @@ -94,20 +94,20 @@ delim_rule( char ch ) noexcept belongs to the specified character set. The value is a reference to the character in the underlying buffer, expressed as a - @ref string_view. The function @ref squelch + `core::string_view`. The function @ref squelch may be used to turn this into `void` instead. If there is no more input, the error code @ref error::need_more is returned. @par Value Type @code - using value_type = string_view; + using value_type = core::string_view; @endcode @par Example Rules are used with the function @ref parse. @code - result< string_view > rv = parse( "X", delim_rule( alpha_chars ) ); + system::result< core::string_view > rv = parse( "X", delim_rule( alpha_chars ) ); @endcode @param cs The character set to use. @@ -126,7 +126,7 @@ delim_rule( CharSet const& cs ) noexcept; template struct cs_delim_rule { - using value_type = string_view; + using value_type = core::string_view; constexpr cs_delim_rule( @@ -135,7 +135,7 @@ struct cs_delim_rule { } - result + system::result parse( char const*& it, char const* end) const noexcept @@ -152,7 +152,7 @@ struct cs_delim_rule BOOST_URL_RETURN_EC( error::mismatch); } - return string_view{ + return core::string_view{ it++, 1 }; } diff --git a/boost/url/grammar/detail/ci_string.hpp b/boost/url/grammar/detail/ci_string.hpp index e2ae2b4..9cdf03b 100644 --- a/boost/url/grammar/detail/ci_string.hpp +++ b/boost/url/grammar/detail/ci_string.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP #define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP -#include +#include #include #include #include @@ -111,9 +111,9 @@ ci_is_equal( S1 const& s1) -> typename std::enable_if< ! std::is_convertible< - S0, string_view>::value || + S0, core::string_view>::value || ! std::is_convertible< - S1, string_view>::value, + S1, core::string_view>::value, bool>::type { /* If you get a compile error here, it @@ -162,14 +162,14 @@ ci_is_equal( BOOST_URL_DECL bool ci_is_equal( - string_view s0, - string_view s1) noexcept; + core::string_view s0, + core::string_view s1) noexcept; BOOST_URL_DECL bool ci_is_less( - string_view s0, - string_view s1) noexcept; + core::string_view s0, + core::string_view s1) noexcept; } // detail } // grammar diff --git a/boost/url/grammar/detail/impl/ci_string.ipp b/boost/url/grammar/detail/impl/ci_string.ipp deleted file mode 100644 index 4854acf..0000000 --- a/boost/url/grammar/detail/impl/ci_string.ipp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/url -// - -#ifndef BOOST_URL_GRAMMAR_DETAIL_IMPL_CI_STRING_IPP -#define BOOST_URL_GRAMMAR_DETAIL_IMPL_CI_STRING_IPP - -#include - -namespace boost { -namespace urls { -namespace grammar { -namespace detail { - -//------------------------------------------------ - -// https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/ -// https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2020/04/30/tolower.cpp - -bool -ci_is_equal( - string_view s0, - string_view s1) noexcept -{ - auto n = s0.size(); - auto p1 = s0.data(); - auto p2 = s1.data(); - char a, b; - // fast loop - while(n--) - { - a = *p1++; - b = *p2++; - if(a != b) - goto slow; - } - return true; -slow: - do - { - if( to_lower(a) != - to_lower(b)) - return false; - a = *p1++; - b = *p2++; - } - while(n--); - return true; -} - -//------------------------------------------------ - -bool -ci_is_less( - string_view s0, - string_view s1) noexcept -{ - auto p1 = s0.data(); - auto p2 = s1.data(); - for(auto n = s0.size();n--;) - { - auto c1 = to_lower(*p1++); - auto c2 = to_lower(*p2++); - if(c1 != c2) - return c1 < c2; - } - // equal - return false; -} - -} // detail -} // grammar -} // urls -} // boost - -#endif diff --git a/boost/url/grammar/digit_chars.hpp b/boost/url/grammar/digit_chars.hpp index a48b0b8..d5aa753 100644 --- a/boost/url/grammar/digit_chars.hpp +++ b/boost/url/grammar/digit_chars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > rv = parse( "2022", token_rule( digit_chars ) ); + system::result< core::string_view > rv = parse( "2022", token_rule( digit_chars ) ); @endcode @par BNF diff --git a/boost/url/grammar/hexdig_chars.hpp b/boost/url/grammar/hexdig_chars.hpp index 6ecf236..2f34f30 100644 --- a/boost/url/grammar/hexdig_chars.hpp +++ b/boost/url/grammar/hexdig_chars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) ); + system::result< core::string_view > rv = parse( "8086FC19", token_rule( hexdig_chars ) ); @endcode @par BNF diff --git a/boost/url/grammar/impl/error.hpp b/boost/url/grammar/impl/error.hpp index ef8dec0..a92a1cb 100644 --- a/boost/url/grammar/impl/error.hpp +++ b/boost/url/grammar/impl/error.hpp @@ -39,16 +39,24 @@ struct BOOST_SYMBOL_VISIBLE error_cat_type : system::error_category { - BOOST_URL_DECL const char* name( + BOOST_URL_DECL + const char* name( ) const noexcept override; - BOOST_URL_DECL std::string message( + + BOOST_URL_DECL + std::string message( int) const override; - BOOST_URL_DECL char const* message( + + BOOST_URL_DECL + char const* message( int, char*, std::size_t ) const noexcept override; - BOOST_URL_DECL system::error_condition + + BOOST_URL_DECL + system::error_condition default_error_condition( int code) const noexcept override; + BOOST_SYSTEM_CONSTEXPR error_cat_type() noexcept : error_category(0x0536e50a30f9e9f2) { @@ -59,19 +67,31 @@ struct BOOST_SYMBOL_VISIBLE condition_cat_type : system::error_category { - BOOST_URL_DECL const char* name( + BOOST_URL_DECL + const char* name( ) const noexcept override; - BOOST_URL_DECL std::string message( + + BOOST_URL_DECL + std::string message( int) const override; - BOOST_URL_DECL char const* message( + + BOOST_URL_DECL + char const* message( int, char*, std::size_t ) const noexcept override; + BOOST_SYSTEM_CONSTEXPR condition_cat_type() : error_category(0x0536e50a30f9e9f2) { } }; +BOOST_URL_DECL extern + error_cat_type error_cat; + +BOOST_URL_DECL extern + condition_cat_type condition_cat; + } // detail inline @@ -79,11 +99,10 @@ system::error_code make_error_code( error ev) noexcept { - static BOOST_SYSTEM_CONSTEXPR - detail::error_cat_type cat{}; return system::error_code{ static_cast::type>(ev), cat}; + error>::type>(ev), + detail::error_cat}; } inline @@ -91,11 +110,10 @@ system::error_condition make_error_condition( condition c) noexcept { - static BOOST_SYSTEM_CONSTEXPR - detail::condition_cat_type cat{}; return system::error_condition{ static_cast::type>(c), cat}; + condition>::type>(c), + detail::condition_cat}; } } // grammar diff --git a/boost/url/grammar/impl/not_empty_rule.hpp b/boost/url/grammar/impl/not_empty_rule.hpp index 37689b9..6831558 100644 --- a/boost/url/grammar/impl/not_empty_rule.hpp +++ b/boost/url/grammar/impl/not_empty_rule.hpp @@ -23,7 +23,7 @@ not_empty_rule_t:: parse( char const*& it, char const* end) const -> - result + system::result { if(it == end) { diff --git a/boost/url/grammar/impl/optional_rule.hpp b/boost/url/grammar/impl/optional_rule.hpp index e3c6c0f..8e12565 100644 --- a/boost/url/grammar/impl/optional_rule.hpp +++ b/boost/url/grammar/impl/optional_rule.hpp @@ -22,7 +22,7 @@ optional_rule_t:: parse( char const*& it, char const* end) const -> - result + system::result { if(it == end) return boost::none; diff --git a/boost/url/grammar/impl/parse.hpp b/boost/url/grammar/impl/parse.hpp index f03631f..5bb6878 100644 --- a/boost/url/grammar/impl/parse.hpp +++ b/boost/url/grammar/impl/parse.hpp @@ -24,7 +24,7 @@ parse( char const*& it, char const* end, R const& r) -> - result + system::result { // If this goes off, it means the rule // passed in did not meet the requirements. @@ -40,9 +40,9 @@ template BOOST_URL_NO_INLINE auto parse( - string_view s, + core::string_view s, R const& r) -> - result + system::result { // If this goes off, it means the rule // passed in did not meet the requirements. diff --git a/boost/url/grammar/impl/range_rule.hpp b/boost/url/grammar/impl/range_rule.hpp index 2191991..4280650 100644 --- a/boost/url/grammar/impl/range_rule.hpp +++ b/boost/url/grammar/impl/range_rule.hpp @@ -59,21 +59,21 @@ struct range:: } virtual - result + system::result first( char const*&, char const*) const noexcept { - return error_code{}; + return system::error_code{}; } virtual - result + system::result next( char const*&, char const*) const noexcept { - return error_code{}; + return system::error_code{}; } }; @@ -113,7 +113,7 @@ private: ::new(dest) impl1(*this); } - result + system::result first( char const*& it, char const* end) @@ -123,7 +123,7 @@ private: it, end, this->get()); } - result + system::result next( char const*& it, char const* end) @@ -188,7 +188,7 @@ private: ::new(dest) impl1(*this); } - result + system::result first( char const*& it, char const* end) @@ -198,7 +198,7 @@ private: it, end, this->get().r); } - result + system::result next( char const*& it, char const* end) @@ -249,7 +249,7 @@ private: ::new(dest) impl2(*this); } - result + system::result first( char const*& it, char const* end) @@ -260,7 +260,7 @@ private: R0,0>::get()); } - result + system::result next( char const*& it, char const* end) @@ -330,7 +330,7 @@ private: ::new(dest) impl2(*this); } - result + system::result first( char const*& it, char const* end) @@ -340,7 +340,7 @@ private: it, end, get().first); } - result + system::result next( char const*& it, char const* end) @@ -427,7 +427,7 @@ private: range const* r_ = nullptr; char const* p_ = nullptr; - result rv_; + system::result rv_; iterator( range const& r) noexcept @@ -458,7 +458,7 @@ template template range:: range( - string_view s, + core::string_view s, std::size_t n, R const& next) : s_(s) @@ -480,7 +480,7 @@ template< class R0, class R1> range:: range( - string_view s, + core::string_view s, std::size_t n, R0 const& first, R1 const& next) @@ -604,7 +604,7 @@ range_rule_t:: parse( char const*& it, char const* end) const -> - result + system::result { using T = typename R::value_type; @@ -628,7 +628,7 @@ parse( } // good return range( - string_view(it0, it - it0), + core::string_view(it0, it - it0), n, next_); } for(;;) @@ -661,7 +661,7 @@ parse( } // good return range( - string_view(it0, it - it0), + core::string_view(it0, it - it0), n, next_); } @@ -673,7 +673,7 @@ range_rule_t:: parse( char const*& it, char const* end) const -> - result> { using T = typename R0::value_type; @@ -698,7 +698,7 @@ parse( } // good return range( - string_view(it0, it - it0), + core::string_view(it0, it - it0), n, first_, next_); } for(;;) @@ -731,7 +731,7 @@ parse( } // good return range( - string_view(it0, it - it0), + core::string_view(it0, it - it0), n, first_, next_); } diff --git a/boost/url/grammar/impl/token_rule.hpp b/boost/url/grammar/impl/token_rule.hpp index 1ec063a..da01dda 100644 --- a/boost/url/grammar/impl/token_rule.hpp +++ b/boost/url/grammar/impl/token_rule.hpp @@ -23,7 +23,7 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { auto const it0 = it; if(it == end) @@ -33,7 +33,7 @@ parse( } it = (find_if_not)(it, end, cs_); if(it != it0) - return string_view(it0, it - it0); + return core::string_view(it0, it - it0); BOOST_URL_RETURN_EC( error::mismatch); } diff --git a/boost/url/grammar/impl/tuple_rule.hpp b/boost/url/grammar/impl/tuple_rule.hpp index ae2cf13..7d90d38 100644 --- a/boost/url/grammar/impl/tuple_rule.hpp +++ b/boost/url/grammar/impl/tuple_rule.hpp @@ -36,15 +36,15 @@ struct parse_sequence using V = mp11::mp_remove< std::tuple< - result, - result...>, - result>; + system::result, + system::result...>, + system::result>; template using is_void = std::is_same< mp11::mp_at_c, void>; - error_code ec; + system::error_code ec; R const& rn; V vn; @@ -53,7 +53,7 @@ struct parse_sequence R const& rn_) noexcept : rn(rn_) , vn(mp11::mp_fill< - V, error_code>{}) + V, system::error_code>{}) { } @@ -65,7 +65,7 @@ struct parse_sequence { } - // for result + // for system::result template< std::size_t Ir, std::size_t Iv> @@ -77,7 +77,7 @@ struct parse_sequence mp11::mp_size_t const&, mp11::mp_true const&) { - result rv = + system::result rv = grammar::parse( it, end, get(rn)); if( !rv ) @@ -142,7 +142,7 @@ struct parse_sequence auto make_result() noexcept -> - result::value_type> { if(ec.failed()) @@ -165,9 +165,9 @@ struct parse_sequence using V = mp11::mp_first< mp11::mp_remove< mp11::mp_list< - result, - result...>, - result>>; + system::result, + system::result...>, + system::result>>; template using is_void = std::is_same< @@ -180,7 +180,7 @@ struct parse_sequence parse_sequence( R const& rn_) noexcept : rn(rn_) - , v(error_code{}) + , v(system::error_code{}) { } @@ -192,7 +192,7 @@ struct parse_sequence { } - // for result + // for system::result template< std::size_t Ir, std::size_t Iv> @@ -205,7 +205,7 @@ struct parse_sequence mp11::mp_size_t const&, mp11::mp_true const&) { - result rv = + system::result rv = grammar::parse( it, end, get(rn)); if( !rv ) @@ -270,7 +270,7 @@ tuple_rule_t:: parse( char const*& it, char const* end) const -> - result + system::result { detail::parse_sequence< IsList, R0, Rn...> t(this->get()); diff --git a/boost/url/grammar/impl/unsigned_rule.hpp b/boost/url/grammar/impl/unsigned_rule.hpp index f45d371..0eb0ce5 100644 --- a/boost/url/grammar/impl/unsigned_rule.hpp +++ b/boost/url/grammar/impl/unsigned_rule.hpp @@ -25,7 +25,7 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { if(it == end) { diff --git a/boost/url/grammar/impl/variant_rule.hpp b/boost/url/grammar/impl/variant_rule.hpp index 86f12e0..26db32b 100644 --- a/boost/url/grammar/impl/variant_rule.hpp +++ b/boost/url/grammar/impl/variant_rule.hpp @@ -35,7 +35,7 @@ parse_variant( std::integral_constant< std::size_t, I> const&, std::false_type const&) -> - result> { @@ -57,7 +57,7 @@ parse_variant( std::integral_constant< std::size_t, I> const&, std::true_type const&) -> - result> { @@ -87,7 +87,7 @@ variant_rule_t:: parse( char const*& it, char const* end) const -> - result + system::result { return detail::parse_variant( it, end, rn_, diff --git a/boost/url/grammar/literal_rule.hpp b/boost/url/grammar/literal_rule.hpp index 5bc51da..31c148d 100644 --- a/boost/url/grammar/literal_rule.hpp +++ b/boost/url/grammar/literal_rule.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -28,13 +28,13 @@ namespace grammar { @par Value Type @code - using value_type = string_view; + using value_type = core::string_view; @endcode @par Example Rules are used with the function @ref parse. @code - result< string_view > rv = parse( "HTTP", literal_rule( "HTTP" ) ); + system::result< core::string_view > rv = parse( "HTTP", literal_rule( "HTTP" ) ); @endcode @see @@ -62,7 +62,7 @@ class literal_rule } public: - using value_type = string_view; + using value_type = core::string_view; constexpr explicit @@ -74,7 +74,7 @@ public: } BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end) const noexcept; diff --git a/boost/url/grammar/lut_chars.hpp b/boost/url/grammar/lut_chars.hpp index e378082..0454a8a 100644 --- a/boost/url/grammar/lut_chars.hpp +++ b/boost/url/grammar/lut_chars.hpp @@ -52,7 +52,7 @@ struct is_pred rv = parse( "Aiea", token_rule( vowel_chars ) ); + system::result< core::string_view > rv = parse( "Aiea", token_rule( vowel_chars ) ); @endcode @see diff --git a/boost/url/grammar/not_empty_rule.hpp b/boost/url/grammar/not_empty_rule.hpp index 7ba5db6..2aa732d 100644 --- a/boost/url/grammar/not_empty_rule.hpp +++ b/boost/url/grammar/not_empty_rule.hpp @@ -32,7 +32,7 @@ namespace grammar { @par Example Rules are used with the function @ref parse. @code - result< decode_view > rv = parse( "Program%20Files", + system::result< decode_view > rv = parse( "Program%20Files", not_empty_rule( pct_encoded_rule( unreserved_chars ) ) ); @endcode @@ -59,7 +59,7 @@ struct not_empty_rule_t parse( char const*& it, char const* end) const -> - result; + system::result; template friend diff --git a/boost/url/grammar/optional_rule.hpp b/boost/url/grammar/optional_rule.hpp index bdfe2f9..c3443f0 100644 --- a/boost/url/grammar/optional_rule.hpp +++ b/boost/url/grammar/optional_rule.hpp @@ -35,7 +35,7 @@ namespace grammar { @par Example Rules are used with the function @ref grammar::parse. @code - result< optional< string_view > > rv = parse( "", optional_rule( token_rule( alpha_chars ) ) ); + system::result< optional< core::string_view > > rv = parse( "", optional_rule( token_rule( alpha_chars ) ) ); @endcode @par BNF @@ -65,10 +65,10 @@ template struct optional_rule_t : private empty_value { - using value_type = optional< + using value_type = boost::optional< typename Rule::value_type>; - result + system::result parse( char const*& it, char const* end) const; diff --git a/boost/url/grammar/parse.hpp b/boost/url/grammar/parse.hpp index ff46f54..c5491d6 100644 --- a/boost/url/grammar/parse.hpp +++ b/boost/url/grammar/parse.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -38,7 +38,7 @@ namespace grammar { @ref result. */ template -result +system::result parse( char const*& it, char const* end, @@ -62,9 +62,9 @@ parse( @ref result. */ template -result +system::result parse( - string_view s, + core::string_view s, Rule const& r); //------------------------------------------------ @@ -80,7 +80,7 @@ struct rule_ref using value_type = typename Rule::value_type; - result + system::result parse( char const*& it, char const* end) const diff --git a/boost/url/grammar/range_rule.hpp b/boost/url/grammar/range_rule.hpp index 49c77f0..24d99af 100644 --- a/boost/url/grammar/range_rule.hpp +++ b/boost/url/grammar/range_rule.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include #include @@ -80,7 +80,7 @@ class range }; small_buffer sb_; - string_view s_; + core::string_view s_; std::size_t n_ = 0; //-------------------------------------------- @@ -115,14 +115,14 @@ class range template range( - string_view s, + core::string_view s, std::size_t n, R const& r); template< class R0, class R1> range( - string_view s, + core::string_view s, std::size_t n, R0 const& first, R1 const& next); @@ -263,7 +263,7 @@ public: /** Return the matching part of the string */ - string_view + core::string_view string() const noexcept { return s_; @@ -307,7 +307,7 @@ struct range_rule_t; @code // range = 1*( ";" token ) - result< range > rv = parse( ";alpha;xray;charlie", + system::result< range > rv = parse( ";alpha;xray;charlie", range_rule( tuple_rule( squelch( delim_rule( ';' ) ), @@ -361,7 +361,7 @@ struct range_rule_t using value_type = range; - result + system::result parse( char const*& it, char const* end) const; @@ -445,7 +445,7 @@ range_rule( @code // range = [ token ] *( "," token ) - result< range< string_view > > rv = parse( "whiskey,tango,foxtrot", + system::result< range< core::string_view > > rv = parse( "whiskey,tango,foxtrot", range_rule( token_rule( alpha_chars ), // first tuple_rule( // next @@ -506,7 +506,7 @@ struct range_rule_t using value_type = range; - result + system::result parse( char const*& it, char const* end) const; diff --git a/boost/url/grammar/string_token.hpp b/boost/url/grammar/string_token.hpp index ef817ed..442ac7b 100644 --- a/boost/url/grammar/string_token.hpp +++ b/boost/url/grammar/string_token.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_GRAMMAR_STRING_TOKEN_HPP #include -#include +#include #include #include #include @@ -268,7 +268,7 @@ assign_to( //------------------------------------------------ -/** A token for producing a durable string_view from a temporary string +/** A token for producing a durable core::string_view from a temporary string */ #ifdef BOOST_URL_DOCS template< @@ -285,7 +285,7 @@ template struct preserve_size_t : arg { - using result_type = string_view; + using result_type = core::string_view; using string_type = std::basic_string< char, std::char_traits, @@ -312,7 +312,7 @@ struct preserve_size_t result_type result() noexcept { - return string_view( + return core::string_view( s_.data(), n_); } diff --git a/boost/url/grammar/string_view_base.hpp b/boost/url/grammar/string_view_base.hpp index 0db1f70..c623d9f 100644 --- a/boost/url/grammar/string_view_base.hpp +++ b/boost/url/grammar/string_view_base.hpp @@ -11,7 +11,8 @@ #define BOOST_URL_GRAMMAR_STRING_VIEW_BASE_HPP #include -#include +#include +#include #include #include #include @@ -37,13 +38,13 @@ class string_view_base protected: /** The referenced character buffer */ - string_view s_; + core::string_view s_; /** Constructor */ constexpr string_view_base( - string_view s) noexcept + core::string_view s) noexcept : s_(s) { } @@ -109,14 +110,14 @@ public: typedef std::ptrdiff_t difference_type; /// A constant used to represent "no position" - static constexpr std::size_t npos = string_view::npos; + static constexpr std::size_t npos = core::string_view::npos; //-------------------------------------------- /** Conversion */ operator - string_view() const noexcept + core::string_view() const noexcept { return s_; } @@ -151,7 +152,7 @@ public: /** Return an iterator to the beginning - See `string_view::begin` + See `core::string_view::begin` */ BOOST_CONSTEXPR const_iterator begin() const noexcept { @@ -160,7 +161,7 @@ public: /** Return an iterator to the end - See `string_view::end` + See `core::string_view::end` */ BOOST_CONSTEXPR const_iterator end() const noexcept { @@ -169,7 +170,7 @@ public: /** Return an iterator to the beginning - See `string_view::cbegin` + See `core::string_view::cbegin` */ BOOST_CONSTEXPR const_iterator cbegin() const noexcept { @@ -178,7 +179,7 @@ public: /** Return an iterator to the end - See `string_view::cend` + See `core::string_view::cend` */ BOOST_CONSTEXPR const_iterator cend() const noexcept { @@ -187,7 +188,7 @@ public: /** Return a reverse iterator to the end - See `string_view::rbegin` + See `core::string_view::rbegin` */ #ifdef __cpp_lib_array_constexpr constexpr @@ -199,7 +200,7 @@ public: /** Return a reverse iterator to the beginning - See `string_view::rend` + See `core::string_view::rend` */ #ifdef __cpp_lib_array_constexpr constexpr @@ -211,7 +212,7 @@ public: /** Return a reverse iterator to the end - See `string_view::crbegin` + See `core::string_view::crbegin` */ #ifdef __cpp_lib_array_constexpr constexpr @@ -223,7 +224,7 @@ public: /** Return a reverse iterator to the beginning - See `string_view::crend` + See `core::string_view::crend` */ #ifdef __cpp_lib_array_constexpr constexpr @@ -237,7 +238,7 @@ public: /** Return the size - See `string_view::size` + See `core::string_view::size` */ BOOST_CONSTEXPR size_type size() const noexcept { @@ -246,7 +247,7 @@ public: /** Return the size - See `string_view::length` + See `core::string_view::length` */ BOOST_CONSTEXPR size_type length() const noexcept { @@ -255,7 +256,7 @@ public: /** Return the maximum allowed size - See `string_view::max_size` + See `core::string_view::max_size` */ BOOST_CONSTEXPR size_type max_size() const noexcept { @@ -264,7 +265,7 @@ public: /** Return true if the string is empty - See `string_view::size` + See `core::string_view::size` */ BOOST_CONSTEXPR bool empty() const noexcept { @@ -275,7 +276,7 @@ public: /** Access a character - See `string_view::operator[]` + See `core::string_view::operator[]` */ BOOST_CXX14_CONSTEXPR const_reference operator[]( size_type pos ) const noexcept @@ -285,7 +286,7 @@ public: /** Access a character - See `string_view::at` + See `core::string_view::at` */ BOOST_CXX14_CONSTEXPR const_reference at( size_type pos ) const @@ -295,7 +296,7 @@ public: /** Return the first character - See `string_view::front` + See `core::string_view::front` */ BOOST_CXX14_CONSTEXPR const_reference front() const noexcept @@ -305,7 +306,7 @@ public: /** Return the last character - See `string_view::back` + See `core::string_view::back` */ BOOST_CXX14_CONSTEXPR const_reference back() const noexcept @@ -315,7 +316,7 @@ public: /** Return a pointer to the character buffer - See `string_view::data` + See `core::string_view::data` */ BOOST_CONSTEXPR const_pointer data() const noexcept @@ -327,7 +328,7 @@ public: /** Copy the characters to another buffer - See `string_view::copy` + See `core::string_view::copy` */ BOOST_CXX14_CONSTEXPR size_type copy( char* s, size_type n, size_type pos = 0 ) const @@ -337,10 +338,10 @@ public: /** Return a view to part of the string - See `string_view::substr` + See `core::string_view::substr` */ - BOOST_CXX14_CONSTEXPR string_view substr( - size_type pos = 0, size_type n = string_view::npos ) const + BOOST_CXX14_CONSTEXPR core::string_view substr( + size_type pos = 0, size_type n = core::string_view::npos ) const { return s_.substr(pos, n); } @@ -349,30 +350,30 @@ public: /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CXX14_CONSTEXPR int - compare( string_view str ) const noexcept + compare( core::string_view str ) const noexcept { return s_.compare(str); } /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CONSTEXPR int compare( - size_type pos1, size_type n1, string_view str ) const + size_type pos1, size_type n1, core::string_view str ) const { return s_.compare(pos1, n1, str); } /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CONSTEXPR int compare( - size_type pos1, size_type n1, string_view str, + size_type pos1, size_type n1, core::string_view str, size_type pos2, size_type n2 ) const { return s_.compare(pos1, n1, str, pos2, n2); @@ -380,7 +381,7 @@ public: /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CONSTEXPR int compare( char const* s ) const noexcept @@ -390,7 +391,7 @@ public: /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, char const* s ) const @@ -400,7 +401,7 @@ public: /** Return the result of comparing to another string - See `string_view::compare` + See `core::string_view::compare` */ BOOST_CONSTEXPR int compare( size_type pos1, size_type n1, @@ -413,17 +414,17 @@ public: /** Return true if a matching prefix exists - See `string_view::starts_with` + See `core::string_view::starts_with` */ BOOST_CONSTEXPR bool starts_with( - string_view x ) const noexcept + core::string_view x ) const noexcept { return s_.starts_with(x); } /** Return true if a matching prefix exists - See `string_view::starts_with` + See `core::string_view::starts_with` */ BOOST_CONSTEXPR bool starts_with( char x ) const noexcept @@ -433,7 +434,7 @@ public: /** Return true if a matching prefix exists - See `string_view::starts_with` + See `core::string_view::starts_with` */ BOOST_CONSTEXPR bool starts_with( char const* x ) const noexcept @@ -445,17 +446,17 @@ public: /** Return true if a matching suffix exists - See `string_view::ends_with` + See `core::string_view::ends_with` */ BOOST_CONSTEXPR bool ends_with( - string_view x ) const noexcept + core::string_view x ) const noexcept { return s_.ends_with(x); } /** Return true if a matching suffix exists - See `string_view::ends_with` + See `core::string_view::ends_with` */ BOOST_CONSTEXPR bool ends_with( char x ) const noexcept @@ -465,7 +466,7 @@ public: /** Return true if a matching suffix exists - See `string_view::ends_with` + See `core::string_view::ends_with` */ BOOST_CONSTEXPR bool ends_with( char const* x ) const noexcept @@ -477,17 +478,17 @@ public: /** Return the position of matching characters - See `string_view::find` + See `core::string_view::find` */ BOOST_CONSTEXPR size_type find( - string_view str, size_type pos = 0 ) const noexcept + core::string_view str, size_type pos = 0 ) const noexcept { return s_.find(str, pos); } /** Return the position of matching characters - See `string_view::find` + See `core::string_view::find` */ BOOST_CXX14_CONSTEXPR size_type find( char c, size_type pos = 0 ) const noexcept @@ -497,7 +498,7 @@ public: /** Return the position of matching characters - See `string_view::find` + See `core::string_view::find` */ BOOST_CXX14_CONSTEXPR size_type find( char const* s, size_type pos, size_type n ) const noexcept @@ -507,7 +508,7 @@ public: /** Return the position of matching characters - See `string_view::find` + See `core::string_view::find` */ BOOST_CONSTEXPR size_type find( char const* s, size_type pos = 0 ) const noexcept @@ -519,27 +520,27 @@ public: /** Return the position of matching characters - See `string_view::rfind` + See `core::string_view::rfind` */ BOOST_CONSTEXPR size_type rfind( - string_view str, size_type pos = string_view::npos ) const noexcept + core::string_view str, size_type pos = core::string_view::npos ) const noexcept { return s_.rfind(str, pos); } /** Return the position of matching characters - See `string_view::rfind` + See `core::string_view::rfind` */ BOOST_CXX14_CONSTEXPR size_type rfind( - char c, size_type pos = string_view::npos ) const noexcept + char c, size_type pos = core::string_view::npos ) const noexcept { return s_.rfind(c, pos); } /** Return the position of matching characters - See `string_view::rfind` + See `core::string_view::rfind` */ BOOST_CXX14_CONSTEXPR size_type rfind( char const* s, size_type pos, size_type n ) const noexcept @@ -549,10 +550,10 @@ public: /** Return the position of matching characters - See `string_view::rfind` + See `core::string_view::rfind` */ BOOST_CONSTEXPR size_type rfind( - char const* s, size_type pos = string_view::npos ) const noexcept + char const* s, size_type pos = core::string_view::npos ) const noexcept { return s_.rfind(s, pos); } @@ -561,17 +562,17 @@ public: /** Return the position of the first match - See `string_view::find_first_of` + See `core::string_view::find_first_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_of( - string_view str, size_type pos = 0 ) const noexcept + core::string_view str, size_type pos = 0 ) const noexcept { return s_.find_first_of(str, pos); } /** Return the position of the first match - See `string_view::find_first_of` + See `core::string_view::find_first_of` */ BOOST_CONSTEXPR size_type find_first_of( char c, size_type pos = 0 ) const noexcept @@ -581,7 +582,7 @@ public: /** Return the position of the first match - See `string_view::find_first_of` + See `core::string_view::find_first_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_of( char const* s, size_type pos, size_type n ) const noexcept @@ -591,7 +592,7 @@ public: /** Return the position of the first match - See `string_view::find_first_of` + See `core::string_view::find_first_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_of( char const* s, size_type pos = 0 ) const noexcept @@ -603,27 +604,27 @@ public: /** Return the position of the last match - See `string_view::find_last_of` + See `core::string_view::find_last_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_of( - string_view str, size_type pos = string_view::npos ) const noexcept + core::string_view str, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_of(str, pos); } /** Return the position of the last match - See `string_view::find_last_of` + See `core::string_view::find_last_of` */ BOOST_CONSTEXPR size_type find_last_of( - char c, size_type pos = string_view::npos ) const noexcept + char c, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_of(c, pos); } /** Return the position of the last match - See `string_view::find_last_of` + See `core::string_view::find_last_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_of( char const* s, size_type pos, size_type n ) const noexcept @@ -633,10 +634,10 @@ public: /** Return the position of the last match - See `string_view::find_last_of` + See `core::string_view::find_last_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_of( - char const* s, size_type pos = string_view::npos ) const noexcept + char const* s, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_of(s, pos); } @@ -645,17 +646,17 @@ public: /** Return the position of the first non-match - See `string_view::find_first_not_of` + See `core::string_view::find_first_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_not_of( - string_view str, size_type pos = 0 ) const noexcept + core::string_view str, size_type pos = 0 ) const noexcept { return s_.find_first_not_of(str, pos); } /** Return the position of the first non-match - See `string_view::find_first_not_of` + See `core::string_view::find_first_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_not_of( char c, size_type pos = 0 ) const noexcept @@ -665,7 +666,7 @@ public: /** Return the position of the first non-match - See `string_view::find_first_not_of` + See `core::string_view::find_first_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_not_of( char const* s, size_type pos, size_type n ) const noexcept @@ -675,7 +676,7 @@ public: /** Return the position of the first non-match - See `string_view::find_first_not_of` + See `core::string_view::find_first_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_first_not_of( char const* s, size_type pos = 0 ) const noexcept @@ -687,27 +688,27 @@ public: /** Return the position of the last non-match - See `string_view::find_last_not_of` + See `core::string_view::find_last_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_not_of( - string_view str, size_type pos = string_view::npos ) const noexcept + core::string_view str, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_not_of(str, pos); } /** Return the position of the last non-match - See `string_view::find_last_not_of` + See `core::string_view::find_last_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_not_of( - char c, size_type pos = string_view::npos ) const noexcept + char c, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_not_of(c, pos); } /** Return the position of the last non-match - See `string_view::find_last_not_of` + See `core::string_view::find_last_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_not_of( char const* s, size_type pos, size_type n ) const noexcept @@ -717,10 +718,10 @@ public: /** Return the position of the last non-match - See `string_view::find_last_not_of` + See `core::string_view::find_last_not_of` */ BOOST_CXX14_CONSTEXPR size_type find_last_not_of( - char const* s, size_type pos = string_view::npos ) const noexcept + char const* s, size_type pos = core::string_view::npos ) const noexcept { return s_.find_last_not_of(s, pos); } @@ -729,16 +730,16 @@ public: /** Return true if matching characters are found - See `string_view::contains` + See `core::string_view::contains` */ - BOOST_CONSTEXPR bool contains( string_view sv ) const noexcept + BOOST_CONSTEXPR bool contains( core::string_view sv ) const noexcept { return s_.contains(sv); } /** Return true if matching characters are found - See `string_view::contains` + See `core::string_view::contains` */ BOOST_CXX14_CONSTEXPR bool contains( char c ) const noexcept { @@ -747,7 +748,7 @@ public: /** Return true if matching characters are found - See `string_view::contains` + See `core::string_view::contains` */ BOOST_CONSTEXPR bool contains( char const* s ) const noexcept { @@ -759,8 +760,8 @@ public: private: template using is_match = std::integral_constant::value && - std::is_convertible::value && ( + std::is_convertible::value && + std::is_convertible::value && ( (std::is_base_of::type>::value && std::is_convertible inline -string_view +core::string_view to_sv(grammar::string_view_base const& s) noexcept { - return s.operator string_view(); + return s.operator core::string_view(); } } // detail #endif diff --git a/boost/url/grammar/token_rule.hpp b/boost/url/grammar/token_rule.hpp index dbb8ec2..323906f 100644 --- a/boost/url/grammar/token_rule.hpp +++ b/boost/url/grammar/token_rule.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace boost { namespace urls { @@ -26,13 +26,13 @@ namespace grammar { @par Value Type @code - using value_type = string_view; + using value_type = core::string_view; @endcode @par Example Rules are used with the function @ref parse. @code - result< string_view > rv = parse( "abcdef", token_rule( alpha_chars ) ); + system::result< core::string_view > rv = parse( "abcdef", token_rule( alpha_chars ) ); @endcode @par BNF @@ -56,7 +56,7 @@ token_rule( template struct token_rule_t { - using value_type = string_view; + using value_type = core::string_view; static_assert( is_charset::value, @@ -67,7 +67,7 @@ struct token_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; private: template diff --git a/boost/url/grammar/tuple_rule.hpp b/boost/url/grammar/tuple_rule.hpp index a35add1..9b8fdea 100644 --- a/boost/url/grammar/tuple_rule.hpp +++ b/boost/url/grammar/tuple_rule.hpp @@ -42,13 +42,13 @@ namespace grammar { except that `void` values are removed. However, if there is exactly one non-void value type `T`, then the sequence rule - returns `result` instead of - `result>`. + returns `system::result` instead of + `system::result>`. @par Example Rules are used with the function @ref parse. @code - result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv = + system::result< std::tuple< unsigned char, unsigned char, unsigned char, unsigned char > > rv = parse( "192.168.0.1", tuple_rule( dec_octet_rule, @@ -114,7 +114,7 @@ public: Rn_ const&... rn) noexcept -> tuple_rule_t; - result + system::result parse( char const*& it, char const* end) const; @@ -164,7 +164,7 @@ struct squelch_rule_t { } - result + system::result parse( char const*& it, char const* end) const @@ -196,7 +196,7 @@ struct squelch_rule_t @par Example 1 With `squelch`: @code - result< std::tuple< decode_view, string_view > > rv = parse( + system::result< std::tuple< decode_view, core::string_view > > rv = parse( "www.example.com:443", tuple_rule( pct_encoded_rule(unreserved_chars + '-' + '.'), @@ -207,7 +207,7 @@ struct squelch_rule_t @par Example 2 Without `squelch`: @code - result< std::tuple< decode_view, string_view, string_view > > rv = parse( + system::result< std::tuple< decode_view, core::string_view, core::string_view > > rv = parse( "www.example.com:443", tuple_rule( pct_encoded_rule(unreserved_chars + '-' + '.'), diff --git a/boost/url/grammar/type_traits.hpp b/boost/url/grammar/type_traits.hpp index ce50749..f40fd49 100644 --- a/boost/url/grammar/type_traits.hpp +++ b/boost/url/grammar/type_traits.hpp @@ -34,7 +34,7 @@ namespace grammar { parse( char const*& it, char const* end) const -> - result + system::result }; static_assert( is_rule::value, "Requirements not met" ); @@ -52,7 +52,7 @@ struct is_rule : std::false_type {}; template struct is_rule&>() = + std::declval&>() = std::declval().parse( std::declval(), std::declval()) diff --git a/boost/url/grammar/unsigned_rule.hpp b/boost/url/grammar/unsigned_rule.hpp index 9addf3c..85ecc8b 100644 --- a/boost/url/grammar/unsigned_rule.hpp +++ b/boost/url/grammar/unsigned_rule.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,7 +35,7 @@ namespace grammar { @par Example Rules are used with the function @ref parse. @code - result< unsigned short > rv = parse( "32767", unsigned_rule< unsigned short >{} ); + system::result< unsigned short > rv = parse( "32767", unsigned_rule< unsigned short >{} ); @endcode @par BNF @@ -69,7 +69,7 @@ struct unsigned_rule char const*& it, char const* end ) const noexcept -> - result; + system::result; }; #endif diff --git a/boost/url/grammar/variant_rule.hpp b/boost/url/grammar/variant_rule.hpp index f8bcf20..2e08d5e 100644 --- a/boost/url/grammar/variant_rule.hpp +++ b/boost/url/grammar/variant_rule.hpp @@ -39,7 +39,7 @@ namespace grammar { // / authority-form // / asterisk-form - result< variant< url_view, url_view, authority_view, string_view > > rv = grammar::parse( + system::result< variant< url_view, url_view, authority_view, core::string_view > > rv = grammar::parse( "/index.html?width=full", variant_rule( origin_form_rule, @@ -65,8 +65,7 @@ namespace grammar { @ref delim_rule, @ref parse, @ref origin_form_rule, - @ref url_view, - @ref variant. + @ref url_view. */ #ifdef BOOST_URL_DOCS template @@ -87,7 +86,7 @@ public: parse( char const*& it, char const* end) const -> - result; + system::result; template< class R0_, diff --git a/boost/url/grammar/vchars.hpp b/boost/url/grammar/vchars.hpp index 1b161dc..b325e6d 100644 --- a/boost/url/grammar/vchars.hpp +++ b/boost/url/grammar/vchars.hpp @@ -23,7 +23,7 @@ namespace grammar { Character sets are used with rules and the functions @ref find_if and @ref find_if_not. @code - result< string_view > rv = parse( "JohnDoe", token_rule( vchars ) ); + system::result< core::string_view > rv = parse( "JohnDoe", token_rule( vchars ) ); @endcode @par BNF diff --git a/boost/url/impl/encode.hpp b/boost/url/impl/encode.hpp index c9e22d8..f7605c0 100644 --- a/boost/url/impl/encode.hpp +++ b/boost/url/impl/encode.hpp @@ -27,7 +27,7 @@ namespace urls { template std::size_t encoded_size( - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt) noexcept { @@ -80,7 +80,7 @@ std::size_t encode( char* dest, std::size_t size, - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt) { @@ -174,7 +174,7 @@ std::size_t encode_unsafe( char* dest, std::size_t size, - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt) { @@ -249,7 +249,7 @@ template< class CharSet> BOOST_URL_STRTOK_RETURN encode( - string_view s, + core::string_view s, CharSet const& unreserved, encoding_opts opt, StringToken&& token) noexcept diff --git a/boost/url/impl/error.hpp b/boost/url/impl/error.hpp index 23f59d5..5aea1bf 100644 --- a/boost/url/impl/error.hpp +++ b/boost/url/impl/error.hpp @@ -32,16 +32,24 @@ struct BOOST_SYMBOL_VISIBLE error_cat_type : system::error_category { - BOOST_URL_DECL const char* name( + BOOST_URL_DECL + const char* name( ) const noexcept override; - BOOST_URL_DECL std::string message( + + BOOST_URL_DECL + std::string message( int) const override; - BOOST_URL_DECL char const* message( + + BOOST_URL_DECL + char const* message( int, char*, std::size_t ) const noexcept override; - BOOST_URL_DECL system::error_condition + + BOOST_URL_DECL + system::error_condition default_error_condition( int code) const noexcept override; + BOOST_SYSTEM_CONSTEXPR error_cat_type() noexcept : error_category(0xbc15399d7a4ce829) { diff --git a/boost/url/impl/params_base.hpp b/boost/url/impl/params_base.hpp index e08d31d..6536423 100644 --- a/boost/url/impl/params_base.hpp +++ b/boost/url/impl/params_base.hpp @@ -19,7 +19,7 @@ namespace urls { //------------------------------------------------ -class params_base::iterator +class BOOST_URL_DECL params_base::iterator { detail::params_iter_impl it_; bool space_as_plus_ = true; @@ -88,7 +88,6 @@ public: return tmp; } - BOOST_URL_DECL reference operator*() const; @@ -110,84 +109,6 @@ public: } }; -//------------------------------------------------ - -inline -params_base:: -params_base() noexcept - // space_as_plus = true - : opt_(true, false, false) -{ -} - -inline -bool -params_base:: -contains( - string_view key, - ignore_case_param ic) const noexcept -{ - return find( - begin(),key, ic) != end(); -} - -inline -auto -params_base:: -find( - string_view key, - ignore_case_param ic) const noexcept -> - iterator -{ - return iterator( - find_impl( - begin().it_, key, ic), - opt_); -} - -inline -auto -params_base:: -find( - iterator it, - string_view key, - ignore_case_param ic) const noexcept -> - iterator -{ - return iterator( - find_impl( - it.it_, key, ic), - opt_); -} - -inline -auto -params_base:: -find_last( - string_view key, - ignore_case_param ic) const noexcept -> - iterator -{ - return iterator( - find_last_impl( - end().it_, key, ic), - opt_); -} - -inline -auto -params_base:: -find_last( - iterator it, - string_view key, - ignore_case_param ic) const noexcept -> - iterator -{ - return iterator( - find_last_impl( - it.it_, key, ic), - opt_); -} } // urls } // boost diff --git a/boost/url/impl/params_encoded_ref.hpp b/boost/url/impl/params_encoded_ref.hpp index 5330a7a..3776641 100644 --- a/boost/url/impl/params_encoded_ref.hpp +++ b/boost/url/impl/params_encoded_ref.hpp @@ -126,33 +126,6 @@ insert( FwdIt>::iterator_category{}); } -inline -auto -params_encoded_ref:: -erase( - iterator pos) noexcept -> - iterator -{ - return erase( - pos, - std::next(pos)); -} - -inline -auto -params_encoded_ref:: -erase( - iterator first, - iterator last) noexcept -> - iterator -{ - string_view s("", 0); - return u_->edit_params( - first.it_, - last.it_, - detail::query_iter(s)); -} - template auto params_encoded_ref:: diff --git a/boost/url/impl/params_ref.hpp b/boost/url/impl/params_ref.hpp index 3857190..a2367df 100644 --- a/boost/url/impl/params_ref.hpp +++ b/boost/url/impl/params_ref.hpp @@ -166,35 +166,6 @@ insert( FwdIt>::iterator_category{}); } -inline -auto -params_ref:: -erase( - iterator pos) noexcept -> - iterator -{ - return erase( - pos, - std::next(pos)); -} - -inline -auto -params_ref:: -erase( - iterator first, - iterator last) noexcept -> - iterator -{ - string_view s("", 0); - return iterator( - u_->edit_params( - first.it_, - last.it_, - detail::query_iter(s)), - opt_); -} - template auto params_ref:: diff --git a/boost/url/impl/segments_encoded_ref.hpp b/boost/url/impl/segments_encoded_ref.hpp index 134672d..c7929ac 100644 --- a/boost/url/impl/segments_encoded_ref.hpp +++ b/boost/url/impl/segments_encoded_ref.hpp @@ -48,7 +48,7 @@ assign( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); u_->edit_segments( @@ -76,7 +76,7 @@ insert( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); return insert( @@ -116,7 +116,7 @@ replace( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); return u_->edit_segments( diff --git a/boost/url/impl/segments_ref.hpp b/boost/url/impl/segments_ref.hpp index d2e5c00..ef0c066 100644 --- a/boost/url/impl/segments_ref.hpp +++ b/boost/url/impl/segments_ref.hpp @@ -47,7 +47,7 @@ assign(FwdIt first, FwdIt last) std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); u_->edit_segments( @@ -75,7 +75,7 @@ insert( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); return insert( @@ -115,7 +115,7 @@ replace( std::is_convertible< typename std::iterator_traits< FwdIt>::reference, - string_view>::value, + core::string_view>::value, "Type requirements not met"); return u_->edit_segments( @@ -131,7 +131,7 @@ inline void segments_ref:: push_back( - string_view s) + core::string_view s) { insert(end(), s); } diff --git a/boost/url/ipv4_address.hpp b/boost/url/ipv4_address.hpp index 6c817ab..f32d84a 100644 --- a/boost/url/ipv4_address.hpp +++ b/boost/url/ipv4_address.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -145,7 +145,7 @@ public: BOOST_URL_DECL explicit ipv4_address( - string_view s); + core::string_view s); /** Return the address as bytes, in network byte order. */ @@ -215,7 +215,7 @@ public: @param dest_size The size of the output buffer. */ BOOST_URL_DECL - string_view + core::string_view to_buffer( char* dest, std::size_t dest_size) const; @@ -334,9 +334,9 @@ operator<<( /** Return an IPv4 address from an IP address string in dotted decimal form */ BOOST_URL_DECL -result +system::result parse_ipv4_address( - string_view s) noexcept; + core::string_view s) noexcept; } // urls } // boost diff --git a/boost/url/ipv6_address.hpp b/boost/url/ipv6_address.hpp index 2debc8e..06d698b 100644 --- a/boost/url/ipv6_address.hpp +++ b/boost/url/ipv6_address.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include #include @@ -168,7 +168,7 @@ public: */ BOOST_URL_DECL ipv6_address( - string_view s); + core::string_view s); /** Return the address as bytes, in network byte order */ @@ -242,7 +242,7 @@ public: @param dest_size The size of the output buffer. */ BOOST_URL_DECL - string_view + core::string_view to_buffer( char* dest, std::size_t dest_size) const; @@ -388,9 +388,9 @@ operator<<( @param s The string to parse. */ BOOST_URL_DECL -result +system::result parse_ipv6_address( - string_view s) noexcept; + core::string_view s) noexcept; } // urls } // boost diff --git a/boost/url/optional.hpp b/boost/url/optional.hpp index c6a9052..11daaf6 100644 --- a/boost/url/optional.hpp +++ b/boost/url/optional.hpp @@ -17,9 +17,32 @@ namespace boost { namespace urls { /** The type of optional used by the library + + @note This alias is no longer supported and + should not be used in new code. Please use + `boost::optional` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + */ +#ifndef BOOST_URL_DOCS +template +using optional + BOOST_URL_DEPRECATED("Use boost::optional instead") = + boost::optional; +#else template using optional = boost::optional; +#endif } // urls } // boost diff --git a/boost/url/param.hpp b/boost/url/param.hpp index abf8eb1..578cf46 100644 --- a/boost/url/param.hpp +++ b/boost/url/param.hpp @@ -241,7 +241,7 @@ struct param @endcode @code - param qp( "key", optional("value") ); + param qp( "key", optional("value") ); @endcode @code @@ -268,15 +268,15 @@ struct param Calls to allocate may throw. @tparam OptionalString An optional string - type, such as @ref string_view, + type, such as `core::string_view`, `std::nullptr`, @ref no_value_t, or - `optional`. + `optional`. @param key, value The key and value to set. */ template param( - string_view key, + core::string_view key, OptionalString const& value) : param(key, detail::get_optional_string(value)) { @@ -334,13 +334,13 @@ struct param // aggregate construction param( - string_view key, - string_view value, + core::string_view key, + core::string_view value, bool has_value) noexcept : key(key) , value(has_value ? value - : string_view()) + : core::string_view()) , has_value(has_value) { } @@ -348,7 +348,7 @@ struct param private: param( - string_view key, + core::string_view key, detail::optional_string const& value) : param(key, value.s, value.b) { @@ -411,7 +411,7 @@ struct param_view the authority that has final control over how the query is interpreted. */ - string_view key; + core::string_view key; /** The value @@ -419,7 +419,7 @@ struct param_view @ref has_value equal to true. An empty value is distinct from no value. */ - string_view value; + core::string_view value; /** True if a value is present @@ -484,15 +484,15 @@ struct param_view Throws nothing. @tparam OptionalString An optional string - type, such as @ref string_view, + type, such as `core::string_view`, `std::nullptr`, @ref no_value_t, or - `optional`. + `optional`. @param key, value The key and value to set. */ template param_view( - string_view key, + core::string_view key, OptionalString const& value) noexcept : param_view(key, detail::get_optional_string(value)) { @@ -568,13 +568,13 @@ struct param_view // aggregate construction param_view( - string_view key_, - string_view value_, + core::string_view key_, + core::string_view value_, bool has_value_) noexcept : key(key_) , value(has_value_ ? value_ - : string_view()) + : core::string_view()) , has_value(has_value_) { } @@ -582,7 +582,7 @@ struct param_view private: param_view( - string_view key, + core::string_view key, detail::optional_string const& value) : param_view(key, value.s, value.b) { @@ -748,7 +748,7 @@ struct param_pct_view @par Example @code - param_pct_view qp( "key", optional("value") ); + param_pct_view qp( "key", optional("value") ); @endcode @par Postconditions @@ -766,9 +766,9 @@ struct param_pct_view `key` or `value` contains an invalid percent-encoding. @tparam OptionalString An optional - @ref string_view type, such as - `boost::optional` or - `std::optional`. + `core::string_view` type, such as + `boost::optional` or + `std::optional`. @param key, value The key and value to set. */ diff --git a/boost/url/params_base.hpp b/boost/url/params_base.hpp index 4dae5a4..6f5aac2 100644 --- a/boost/url/params_base.hpp +++ b/boost/url/params_base.hpp @@ -36,7 +36,7 @@ namespace urls { @li @ref params_encoded_ref @li @ref params_encoded_view */ -class params_base +class BOOST_URL_DECL params_base { friend class url_view_base; friend class params_ref; @@ -46,7 +46,6 @@ class params_base encoding_opts opt_; params_base() noexcept; - BOOST_URL_DECL params_base( detail::query_ref const& ref, encoding_opts opt) noexcept; @@ -173,7 +172,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL pct_string_view buffer() const noexcept; @@ -190,7 +188,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL bool empty() const noexcept; @@ -207,7 +204,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL std::size_t size() const noexcept; @@ -219,7 +215,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL iterator begin() const noexcept; @@ -231,7 +226,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL iterator end() const noexcept; @@ -267,7 +261,7 @@ public: */ bool contains( - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; /** Return the number of matching keys @@ -299,10 +293,9 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL std::size_t count( - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; /** Find a matching key @@ -347,7 +340,7 @@ public: */ iterator find( - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; /** Find a matching key @@ -393,7 +386,7 @@ public: iterator find( iterator from, - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; /** Find a matching key @@ -433,7 +426,7 @@ public: */ iterator find_last( - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; /** Find a matching key @@ -480,22 +473,20 @@ public: iterator find_last( iterator before, - string_view key, + core::string_view key, ignore_case_param ic = {}) const noexcept; private: - BOOST_URL_DECL detail::params_iter_impl find_impl( detail::params_iter_impl, - string_view, + core::string_view, ignore_case_param) const noexcept; - BOOST_URL_DECL detail::params_iter_impl find_last_impl( detail::params_iter_impl, - string_view, + core::string_view, ignore_case_param) const noexcept; }; diff --git a/boost/url/params_encoded_base.hpp b/boost/url/params_encoded_base.hpp index 7052af5..e6042e7 100644 --- a/boost/url/params_encoded_base.hpp +++ b/boost/url/params_encoded_base.hpp @@ -35,7 +35,7 @@ namespace urls { @li @ref params_encoded_ref @li @ref params_encoded_view */ -class params_encoded_base +class BOOST_URL_DECL params_encoded_base { friend class url_view_base; friend class params_encoded_ref; @@ -173,7 +173,6 @@ public: @li Query string (Wikipedia) */ - BOOST_URL_DECL pct_string_view buffer() const noexcept; @@ -190,7 +189,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL bool empty() const noexcept; @@ -207,7 +205,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL std::size_t size() const noexcept; @@ -219,7 +216,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL iterator begin() const noexcept; @@ -231,7 +227,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL iterator end() const noexcept; @@ -306,7 +301,6 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL std::size_t count( pct_string_view key, @@ -513,14 +507,12 @@ public: ignore_case_param ic = {}) const noexcept; private: - BOOST_URL_DECL detail::params_iter_impl find_impl( detail::params_iter_impl, pct_string_view, ignore_case_param) const noexcept; - BOOST_URL_DECL detail::params_iter_impl find_last_impl( detail::params_iter_impl, diff --git a/boost/url/params_encoded_ref.hpp b/boost/url/params_encoded_ref.hpp index 2d27612..0f0fbc9 100644 --- a/boost/url/params_encoded_ref.hpp +++ b/boost/url/params_encoded_ref.hpp @@ -70,7 +70,7 @@ class params_encoded_view; params and all params after (including `end()`). */ -class params_encoded_ref +class BOOST_URL_DECL params_encoded_ref : public params_encoded_base { friend class url_base; @@ -139,7 +139,6 @@ public: @param other The params to assign. */ - BOOST_URL_DECL params_encoded_ref& operator=( params_encoded_ref const& other); @@ -177,7 +176,6 @@ public: @param init The list of params to assign. */ - BOOST_URL_DECL params_encoded_ref& operator=(std::initializer_list< param_pct_view> init); @@ -190,7 +188,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL operator params_encoded_view() const noexcept; @@ -289,7 +286,6 @@ public: @param init The list of params to assign. */ - BOOST_URL_DECL void assign( std::initializer_list< @@ -472,7 +468,6 @@ public: @param p The param to insert. */ - BOOST_URL_DECL iterator insert( iterator before, @@ -514,7 +509,6 @@ public: @param init The list of params to insert. */ - BOOST_URL_DECL iterator insert( iterator before, @@ -660,7 +654,6 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL std::size_t erase( pct_string_view key, @@ -709,7 +702,6 @@ public: @param p The param to assign. */ - BOOST_URL_DECL iterator replace( iterator pos, @@ -750,7 +742,6 @@ public: @param init The list of params to assign. */ - BOOST_URL_DECL iterator replace( iterator from, @@ -838,7 +829,6 @@ public: @param pos An iterator to the element. */ - BOOST_URL_DECL iterator unset( iterator pos) noexcept; @@ -886,7 +876,6 @@ public: That is, `has_value` for the element is true. */ - BOOST_URL_DECL iterator set( iterator pos, @@ -959,7 +948,6 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL iterator set( pct_string_view key, @@ -967,14 +955,12 @@ public: ignore_case_param ic = {}); private: - BOOST_URL_DECL detail::params_iter_impl find_impl( detail::params_iter_impl, pct_string_view, ignore_case_param) const noexcept; - BOOST_URL_DECL detail::params_iter_impl find_last_impl( detail::params_iter_impl, diff --git a/boost/url/params_encoded_view.hpp b/boost/url/params_encoded_view.hpp index 9b573a5..bef2cf1 100644 --- a/boost/url/params_encoded_view.hpp +++ b/boost/url/params_encoded_view.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include @@ -51,7 +51,7 @@ namespace urls { Changes to the underlying character buffer can invalidate iterators which reference it. */ -class params_encoded_view +class BOOST_URL_DECL params_encoded_view : public params_encoded_base { friend class url_view_base; @@ -162,9 +162,8 @@ public: @li 3.4. Query */ - BOOST_URL_DECL params_encoded_view( - string_view s); + core::string_view s); /** Assignment @@ -221,16 +220,15 @@ public: @par Exception Safety Throws nothing */ - BOOST_URL_DECL operator params_view() const noexcept; //-------------------------------------------- - BOOST_URL_DECL friend - result - parse_query(string_view s) noexcept; + BOOST_URL_DECL + system::result + parse_query(core::string_view s) noexcept; }; } // urls diff --git a/boost/url/params_ref.hpp b/boost/url/params_ref.hpp index 862c9d3..05230eb 100644 --- a/boost/url/params_ref.hpp +++ b/boost/url/params_ref.hpp @@ -77,7 +77,7 @@ class params_view; elements and all elements after (including `end()`). */ -class params_ref +class BOOST_URL_DECL params_ref : public params_base { friend class url_base; @@ -181,7 +181,6 @@ public: @param other The params to assign. */ - BOOST_URL_DECL params_ref& operator=( params_ref const& other); @@ -219,7 +218,6 @@ public: /** Conversion */ - BOOST_URL_DECL operator params_view() const noexcept; @@ -314,7 +312,6 @@ public: @param init The list of params to assign. */ - BOOST_URL_DECL void assign( std::initializer_list< @@ -477,7 +474,6 @@ public: @param p The param to insert. */ - BOOST_URL_DECL iterator insert( iterator before, @@ -515,7 +511,6 @@ public: @param init The list of params to insert. */ - BOOST_URL_DECL iterator insert( iterator before, @@ -654,10 +649,9 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL std::size_t erase( - string_view key, + core::string_view key, ignore_case_param ic = {}) noexcept; //-------------------------------------------- @@ -694,7 +688,6 @@ public: @param p The param to assign. */ - BOOST_URL_DECL iterator replace( iterator pos, @@ -731,7 +724,6 @@ public: @param init The list of params to assign. */ - BOOST_URL_DECL iterator replace( iterator from, @@ -815,7 +807,6 @@ public: @param pos An iterator to the element. */ - BOOST_URL_DECL iterator unset( iterator pos) noexcept; @@ -854,11 +845,10 @@ public: That is, `has_value` for the element is true. */ - BOOST_URL_DECL iterator set( iterator pos, - string_view value); + core::string_view value); /** Set a value @@ -917,28 +907,25 @@ public: here, the comparison is case-insensitive. */ - BOOST_URL_DECL iterator set( - string_view key, - string_view value, + core::string_view key, + core::string_view value, ignore_case_param ic = {}); //-------------------------------------------- private: - BOOST_URL_DECL detail::params_iter_impl find_impl( detail::params_iter_impl, - string_view, + core::string_view, ignore_case_param) const noexcept; - BOOST_URL_DECL detail::params_iter_impl find_last_impl( detail::params_iter_impl, - string_view, + core::string_view, ignore_case_param) const noexcept; template diff --git a/boost/url/params_view.hpp b/boost/url/params_view.hpp index ac83a69..e64ceac 100644 --- a/boost/url/params_view.hpp +++ b/boost/url/params_view.hpp @@ -184,7 +184,7 @@ public: */ BOOST_URL_DECL params_view( - string_view s); + core::string_view s); /** Constructor @@ -251,7 +251,7 @@ public: */ BOOST_URL_DECL params_view( - string_view s, + core::string_view s, encoding_opts opt); /** Assignment diff --git a/boost/url/parse.hpp b/boost/url/parse.hpp index e086eac..38c5448 100644 --- a/boost/url/parse.hpp +++ b/boost/url/parse.hpp @@ -31,7 +31,7 @@ namespace urls { @par Example @code - result< url_view > rv = parse_absolute_uri( "http://example.com/index.htm?id=1" ); + system::result< url_view > rv = parse_absolute_uri( "http://example.com/index.htm?id=1" ); @endcode @par BNF @@ -62,9 +62,9 @@ namespace urls { @ref url_view. */ BOOST_URL_DECL -result +system::result parse_absolute_uri( - string_view s); + core::string_view s); //------------------------------------------------ @@ -81,7 +81,7 @@ parse_absolute_uri( @par Example @code - result< url_view > = parse_origin_form( "/index.htm?layout=mobile" ); + system::result< url_view > = parse_origin_form( "/index.htm?layout=mobile" ); @endcode @par BNF @@ -109,9 +109,9 @@ parse_absolute_uri( @ref url_view. */ BOOST_URL_DECL -result +system::result parse_origin_form( - string_view s); + core::string_view s); //------------------------------------------------ @@ -128,7 +128,7 @@ parse_origin_form( @par Example @code - result< url_view > = parse_relative_ref( "images/dot.gif?v=hide#a" ); + system::result< url_view > = parse_relative_ref( "images/dot.gif?v=hide#a" ); @endcode @par BNF @@ -162,9 +162,9 @@ parse_origin_form( @ref url_view. */ BOOST_URL_DECL -result +system::result parse_relative_ref( - string_view s); + core::string_view s); //------------------------------------------------ @@ -181,7 +181,7 @@ parse_relative_ref( @par Example @code - result< url_view > = parse_uri( "https://www.example.com/index.htm?id=guest#s1" ); + system::result< url_view > = parse_uri( "https://www.example.com/index.htm?id=guest#s1" ); @endcode @par BNF @@ -212,9 +212,9 @@ parse_relative_ref( @ref url_view. */ BOOST_URL_DECL -result +system::result parse_uri( - string_view s); + core::string_view s); //------------------------------------------------ @@ -231,7 +231,7 @@ parse_uri( @par Example @code - result< url_view > = parse_uri_reference( "ws://echo.example.com/?name=boost#demo" ); + system::result< url_view > = parse_uri_reference( "ws://echo.example.com/?name=boost#demo" ); @endcode @par BNF @@ -274,9 +274,9 @@ parse_uri( @ref url_view. */ BOOST_URL_DECL -result +system::result parse_uri_reference( - string_view s); + core::string_view s); } // url } // boost diff --git a/boost/url/parse_path.hpp b/boost/url/parse_path.hpp index 1de2f51..12aead2 100644 --- a/boost/url/parse_path.hpp +++ b/boost/url/parse_path.hpp @@ -45,8 +45,8 @@ namespace urls { @ref segments_encoded_view. */ BOOST_URL_DECL -result -parse_path(string_view s) noexcept; +system::result +parse_path(core::string_view s) noexcept; } // urls } // boost diff --git a/boost/url/parse_query.hpp b/boost/url/parse_query.hpp index b7fb19b..29a69ad 100644 --- a/boost/url/parse_query.hpp +++ b/boost/url/parse_query.hpp @@ -14,7 +14,7 @@ #include #include #include -#include +#include namespace boost { namespace urls { @@ -43,8 +43,8 @@ namespace urls { @ref params_encoded_view. */ BOOST_URL_DECL -result -parse_query(string_view s) noexcept; +system::result +parse_query(core::string_view s) noexcept; } // urls } // boost diff --git a/boost/url/pct_string_view.hpp b/boost/url/pct_string_view.hpp index 07085cb..378cca2 100644 --- a/boost/url/pct_string_view.hpp +++ b/boost/url/pct_string_view.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,7 +37,7 @@ make_pct_string_view_unsafe( std::size_t) noexcept; namespace detail { -string_view& +core::string_view& ref(pct_string_view& s) noexcept; } // detail #endif @@ -47,7 +47,7 @@ ref(pct_string_view& s) noexcept; /** A reference to a valid percent-encoded string Objects of this type behave like a - @ref string_view and have the same interface, + `core::string_view` and have the same interface, but offer an additional invariant: they can only be constructed from strings containing valid percent-escapes. @@ -59,7 +59,7 @@ ref(pct_string_view& s) noexcept; @par Operators The following operators are supported between @ref pct_string_view and any object that is - convertible to @ref string_view + convertible to `core::string_view` @code bool operator==( pct_string_view, pct_string_view ) noexcept; @@ -83,7 +83,7 @@ class pct_string_view final std::size_t) noexcept; friend - string_view& + core::string_view& detail::ref(pct_string_view&) noexcept; #endif @@ -147,11 +147,11 @@ public: @par Postconditions @code - this->data() == string_view(s).data() + this->data() == core::string_view(s).data() @endcode @par Complexity - Linear in `string_view(s).size()`. + Linear in `core::string_view(s).size()`. @par Exception Safety Exceptions thrown on invalid input. @@ -159,7 +159,7 @@ public: @throw system_error The string contains an invalid percent encoding. - @tparam String A type convertible to @ref string_view + @tparam String A type convertible to `core::string_view` @param s The string to construct from. */ @@ -169,7 +169,7 @@ public: , class = typename std::enable_if< std::is_convertible< String, - string_view + core::string_view >::value>::type #endif > @@ -211,7 +211,7 @@ public: char const* s, std::size_t len) : pct_string_view( - string_view(s, len)) + core::string_view(s, len)) { } @@ -239,7 +239,7 @@ public: */ BOOST_URL_DECL pct_string_view( - string_view s); + core::string_view s); /** Assignment @@ -265,9 +265,9 @@ public: friend BOOST_URL_DECL - result + system::result make_pct_string_view( - string_view s) noexcept; + core::string_view s) noexcept; //-------------------------------------------- @@ -391,7 +391,7 @@ namespace detail { // underlying string, to handle // self-intersection on modifiers. inline -string_view& +core::string_view& ref(pct_string_view& s) noexcept { return s.s_; @@ -422,9 +422,9 @@ ref(pct_string_view& s) noexcept @param s The string to validate. */ BOOST_URL_DECL -result +system::result make_pct_string_view( - string_view s) noexcept; + core::string_view s) noexcept; #ifndef BOOST_URL_DOCS // VFALCO semi-private for now @@ -437,7 +437,7 @@ make_pct_string_view_unsafe( { #if 0 BOOST_ASSERT(! make_pct_string_view( - string_view(data, size)).has_error()); + core::string_view(data, size)).has_error()); #endif return pct_string_view( data, size, decoded_size); @@ -448,7 +448,7 @@ make_pct_string_view_unsafe( namespace detail { template <> inline -string_view +core::string_view to_sv(pct_string_view const& s) noexcept { return s.substr(); diff --git a/boost/url/rfc/absolute_uri_rule.hpp b/boost/url/rfc/absolute_uri_rule.hpp index 9d11a92..6e96691 100644 --- a/boost/url/rfc/absolute_uri_rule.hpp +++ b/boost/url/rfc/absolute_uri_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< url_view > rv = grammar::parse( "http://example.com/index.htm?id=1", absolute_uri_rule ); + system::result< url_view > rv = grammar::parse( "http://example.com/index.htm?id=1", absolute_uri_rule ); @endcode @par BNF @@ -62,7 +62,7 @@ struct absolute_uri_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr absolute_uri_rule_t absolute_uri_rule{}; diff --git a/boost/url/rfc/authority_rule.hpp b/boost/url/rfc/authority_rule.hpp index eeab844..57ff296 100644 --- a/boost/url/rfc/authority_rule.hpp +++ b/boost/url/rfc/authority_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< authority_view > rv = grammar::parse( "user:pass@example.com:8080", authority_rule ); + system::result< authority_view > rv = grammar::parse( "user:pass@example.com:8080", authority_rule ); @endcode @par BNF @@ -57,7 +57,7 @@ struct authority_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr authority_rule_t authority_rule{}; diff --git a/boost/url/rfc/detail/charsets.hpp b/boost/url/rfc/detail/charsets.hpp index e65be2b..8263372 100644 --- a/boost/url/rfc/detail/charsets.hpp +++ b/boost/url/rfc/detail/charsets.hpp @@ -73,7 +73,7 @@ param_value_chars = pchars constexpr auto fragment_chars = - pchars + '/' + '?'; + pchars + '/' + '?' + '#'; constexpr auto diff --git a/boost/url/rfc/detail/fragment_part_rule.hpp b/boost/url/rfc/detail/fragment_part_rule.hpp index b4be145..62a3fe0 100644 --- a/boost/url/rfc/detail/fragment_part_rule.hpp +++ b/boost/url/rfc/detail/fragment_part_rule.hpp @@ -39,7 +39,7 @@ struct fragment_part_rule_t bool has_fragment = false; }; - result + system::result parse( char const*& it, char const* end diff --git a/boost/url/rfc/detail/h16_rule.hpp b/boost/url/rfc/detail/h16_rule.hpp index f86fd4a..58ce519 100644 --- a/boost/url/rfc/detail/h16_rule.hpp +++ b/boost/url/rfc/detail/h16_rule.hpp @@ -46,7 +46,7 @@ struct h16_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr h16_rule_t h16_rule{}; diff --git a/boost/url/rfc/detail/hier_part_rule.hpp b/boost/url/rfc/detail/hier_part_rule.hpp index 83c1d99..80d05c8 100644 --- a/boost/url/rfc/detail/hier_part_rule.hpp +++ b/boost/url/rfc/detail/hier_part_rule.hpp @@ -49,7 +49,7 @@ struct hier_part_rule_t char const*& it, char const* const end ) const noexcept -> - result; + system::result; }; constexpr hier_part_rule_t hier_part_rule{}; diff --git a/boost/url/rfc/detail/host_rule.hpp b/boost/url/rfc/detail/host_rule.hpp index a78a193..57b18a0 100644 --- a/boost/url/rfc/detail/host_rule.hpp +++ b/boost/url/rfc/detail/host_rule.hpp @@ -42,7 +42,7 @@ struct host_rule_t { urls::host_type host_type = urls::host_type::none; - string_view match; + core::string_view match; unsigned char addr[16] = {}; pct_string_view name; }; @@ -52,7 +52,7 @@ struct host_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr host_rule_t host_rule{}; diff --git a/boost/url/rfc/detail/ip_literal_rule.hpp b/boost/url/rfc/detail/ip_literal_rule.hpp index 779467b..33a5929 100644 --- a/boost/url/rfc/detail/ip_literal_rule.hpp +++ b/boost/url/rfc/detail/ip_literal_rule.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// Copyright (c) 2022 Alan de Freitas (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -13,7 +14,7 @@ #include #include #include -#include +#include namespace boost { namespace urls { @@ -23,7 +24,7 @@ namespace detail { @par BNF @code - IP-literal = "[" ( IPv6address / IPvFuture ) "]" + IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]" @endcode @par Specification @@ -39,7 +40,7 @@ struct ip_literal_rule_t { bool is_ipv6 = false; ipv6_address ipv6; - string_view ipvfuture; + core::string_view ipvfuture; }; auto @@ -47,7 +48,7 @@ struct ip_literal_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr ip_literal_rule_t ip_literal_rule{}; diff --git a/boost/url/rfc/detail/ipv6_addrz_rule.hpp b/boost/url/rfc/detail/ipv6_addrz_rule.hpp new file mode 100644 index 0000000..a27adfa --- /dev/null +++ b/boost/url/rfc/detail/ipv6_addrz_rule.hpp @@ -0,0 +1,56 @@ +// +// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/url +// + +#ifndef BOOST_URL_RFC_DETAIL_IPV6ADDRZ_RULE_HPP +#define BOOST_URL_RFC_DETAIL_IPV6ADDRZ_RULE_HPP + +#include +#include +#include +#include + +namespace boost { +namespace urls { +namespace detail { + +/** Rule for IPvFuture + + @par BNF + @code + IPv6addrz = IPv6address "%25" ZoneID + ZoneID = 1*( unreserved / pct-encoded ) + @endcode + + @par Specification + @li 3.2.2. Host (rfc3986) +*/ +struct ipv6_addrz_rule_t +{ + struct value_type + { + ipv6_address ipv6; + pct_string_view zone_id; + }; + + auto + parse( + char const*& it, + char const* const end + ) const noexcept -> + system::result; +}; + +constexpr ipv6_addrz_rule_t ipv6_addrz_rule{}; + +} // detail +} // urls +} // boost + +#endif diff --git a/boost/url/rfc/detail/ipvfuture_rule.hpp b/boost/url/rfc/detail/ipvfuture_rule.hpp index 27390e3..6f3a6a4 100644 --- a/boost/url/rfc/detail/ipvfuture_rule.hpp +++ b/boost/url/rfc/detail/ipvfuture_rule.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_RFC_DETAIL_IPVFUTURE_RULE_HPP #include -#include +#include namespace boost { namespace urls { @@ -32,9 +32,9 @@ struct ipvfuture_rule_t { struct value_type { - string_view str; - string_view major; - string_view minor; + core::string_view str; + core::string_view major; + core::string_view minor; }; auto @@ -42,7 +42,7 @@ struct ipvfuture_rule_t char const*& it, char const* const end ) const noexcept -> - result; + system::result; }; constexpr ipvfuture_rule_t ipvfuture_rule{}; diff --git a/boost/url/rfc/detail/port_rule.hpp b/boost/url/rfc/detail/port_rule.hpp index fae7933..22459aa 100644 --- a/boost/url/rfc/detail/port_rule.hpp +++ b/boost/url/rfc/detail/port_rule.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include namespace boost { @@ -37,12 +37,12 @@ struct port_rule { struct value_type { - string_view str; + core::string_view str; std::uint16_t number = 0; bool has_number = false; }; - result + system::result parse( char const*& it, char const* end) const noexcept; @@ -71,7 +71,7 @@ struct port_part_rule_t struct value_type { bool has_port = false; - string_view port; + core::string_view port; bool has_number = false; std::uint16_t port_number = 0; }; @@ -81,7 +81,7 @@ struct port_part_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr port_part_rule_t port_part_rule{}; diff --git a/boost/url/rfc/detail/query_part_rule.hpp b/boost/url/rfc/detail/query_part_rule.hpp index 8fa0fa1..04b2c5a 100644 --- a/boost/url/rfc/detail/query_part_rule.hpp +++ b/boost/url/rfc/detail/query_part_rule.hpp @@ -42,7 +42,7 @@ struct query_part_rule_t char const*& it, char const* end ) const noexcept -> - result + system::result { if( it == end || *it != '?') diff --git a/boost/url/rfc/detail/reg_name_rule.hpp b/boost/url/rfc/detail/reg_name_rule.hpp index 53d514a..2f552b8 100644 --- a/boost/url/rfc/detail/reg_name_rule.hpp +++ b/boost/url/rfc/detail/reg_name_rule.hpp @@ -12,6 +12,7 @@ #include #include +#include #include namespace boost { diff --git a/boost/url/rfc/detail/relative_part_rule.hpp b/boost/url/rfc/detail/relative_part_rule.hpp index e9d61c5..7d37f8f 100644 --- a/boost/url/rfc/detail/relative_part_rule.hpp +++ b/boost/url/rfc/detail/relative_part_rule.hpp @@ -55,7 +55,7 @@ struct relative_part_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr relative_part_rule_t relative_part_rule{}; diff --git a/boost/url/rfc/detail/scheme_rule.hpp b/boost/url/rfc/detail/scheme_rule.hpp index 29c1539..a97557c 100644 --- a/boost/url/rfc/detail/scheme_rule.hpp +++ b/boost/url/rfc/detail/scheme_rule.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace boost { namespace urls { @@ -37,12 +37,12 @@ struct scheme_rule { struct value_type { - string_view scheme; + core::string_view scheme; urls::scheme scheme_id = urls::scheme::unknown; }; - result + system::result parse( char const*& it, char const* end) const noexcept; diff --git a/boost/url/rfc/detail/userinfo_rule.hpp b/boost/url/rfc/detail/userinfo_rule.hpp index 15550e7..bd66ff1 100644 --- a/boost/url/rfc/detail/userinfo_rule.hpp +++ b/boost/url/rfc/detail/userinfo_rule.hpp @@ -46,7 +46,7 @@ struct userinfo_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr userinfo_rule_t userinfo_rule{}; diff --git a/boost/url/rfc/gen_delim_chars.hpp b/boost/url/rfc/gen_delim_chars.hpp index b1ffc3d..bc50d6e 100644 --- a/boost/url/rfc/gen_delim_chars.hpp +++ b/boost/url/rfc/gen_delim_chars.hpp @@ -23,7 +23,7 @@ namespace urls { the functions @ref grammar::find_if and @ref grammar::find_if_not. @code - result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( gen_delim_chars ) ); + system::result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( gen_delim_chars ) ); @endcode @par BNF diff --git a/boost/url/rfc/impl/pct_encoded_rule.hpp b/boost/url/rfc/impl/pct_encoded_rule.hpp index 7d21502..2b93f65 100644 --- a/boost/url/rfc/impl/pct_encoded_rule.hpp +++ b/boost/url/rfc/impl/pct_encoded_rule.hpp @@ -25,7 +25,7 @@ parse_encoded( char const*& it, char const* end, CharSet const& cs) noexcept -> - result + system::result { auto const start = it; std::size_t n = 0; @@ -91,7 +91,7 @@ pct_encoded_rule_t:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { return detail::parse_encoded( it, end, cs_); diff --git a/boost/url/rfc/ipv4_address_rule.hpp b/boost/url/rfc/ipv4_address_rule.hpp index 3be02d7..aff5fb8 100644 --- a/boost/url/rfc/ipv4_address_rule.hpp +++ b/boost/url/rfc/ipv4_address_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< ipv4_address > rv = grammar::parse( "192.168.0.1", ipv4_address_rule ); + system::result< ipv4_address > rv = grammar::parse( "192.168.0.1", ipv4_address_rule ); @endcode @par BNF @@ -66,7 +66,7 @@ struct ipv4_address_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr ipv4_address_rule_t ipv4_address_rule{}; diff --git a/boost/url/rfc/ipv6_address_rule.hpp b/boost/url/rfc/ipv6_address_rule.hpp index 12cb7cb..0ddfa1e 100644 --- a/boost/url/rfc/ipv6_address_rule.hpp +++ b/boost/url/rfc/ipv6_address_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< ipv6_address > rv = grammar::parse( "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ipv6_address_rule ); + system::result< ipv6_address > rv = grammar::parse( "2001:0db8:85a3:0000:0000:8a2e:0370:7334", ipv6_address_rule ); @endcode @par BNF @@ -74,7 +74,7 @@ struct ipv6_address_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr ipv6_address_rule_t ipv6_address_rule{}; diff --git a/boost/url/rfc/origin_form_rule.hpp b/boost/url/rfc/origin_form_rule.hpp index 82baf8b..22782f7 100644 --- a/boost/url/rfc/origin_form_rule.hpp +++ b/boost/url/rfc/origin_form_rule.hpp @@ -28,7 +28,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< url_view > rv = grammar::parse( "/index.htm?layout=mobile", origin_form_rule ); + system::result< url_view > rv = grammar::parse( "/index.htm?layout=mobile", origin_form_rule ); @endcode @par BNF @@ -56,7 +56,7 @@ struct origin_form_rule_t url_view; BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end diff --git a/boost/url/rfc/pchars.hpp b/boost/url/rfc/pchars.hpp index 9f7d575..f4512fc 100644 --- a/boost/url/rfc/pchars.hpp +++ b/boost/url/rfc/pchars.hpp @@ -24,7 +24,7 @@ namespace urls { the functions @ref grammar::find_if and @ref grammar::find_if_not. @code - result< decode_view > rv = grammar::parse( "Program%20Files", pchars ); + system::result< decode_view > rv = grammar::parse( "Program%20Files", pchars ); @endcode @par BNF diff --git a/boost/url/rfc/pct_encoded_rule.hpp b/boost/url/rfc/pct_encoded_rule.hpp index 650f5b6..66b7055 100644 --- a/boost/url/rfc/pct_encoded_rule.hpp +++ b/boost/url/rfc/pct_encoded_rule.hpp @@ -35,7 +35,7 @@ namespace urls { @code // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - result< pct_string_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( pchars ) ); + system::result< pct_string_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( pchars ) ); @endcode @par BNF @@ -78,7 +78,7 @@ struct pct_encoded_rule_t CharSet_ const& cs) noexcept -> pct_encoded_rule_t; - result + system::result parse( char const*& it, char const* end) const noexcept; diff --git a/boost/url/rfc/query_rule.hpp b/boost/url/rfc/query_rule.hpp index 7e042b8..06b446d 100644 --- a/boost/url/rfc/query_rule.hpp +++ b/boost/url/rfc/query_rule.hpp @@ -28,7 +28,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< params_encoded_view > rv = grammar::parse( "format=web&id=42&compact", query_rule ); + system::result< params_encoded_view > rv = grammar::parse( "format=web&id=42&compact", query_rule ); @endcode @par BNF @@ -62,7 +62,7 @@ struct query_rule_t using value_type = params_encoded_view; BOOST_URL_DECL - result + system::result parse( char const*& it, char const* end diff --git a/boost/url/rfc/relative_ref_rule.hpp b/boost/url/rfc/relative_ref_rule.hpp index 5110326..ef553f5 100644 --- a/boost/url/rfc/relative_ref_rule.hpp +++ b/boost/url/rfc/relative_ref_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< url_view > rv = grammar::parse( "images/dot.gif?v=hide#a", relative_ref_rule ); + system::result< url_view > rv = grammar::parse( "images/dot.gif?v=hide#a", relative_ref_rule ); @endcode @par BNF @@ -57,7 +57,7 @@ struct relative_ref_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr relative_ref_rule_t relative_ref_rule{}; diff --git a/boost/url/rfc/reserved_chars.hpp b/boost/url/rfc/reserved_chars.hpp index 95361f3..f21c208 100644 --- a/boost/url/rfc/reserved_chars.hpp +++ b/boost/url/rfc/reserved_chars.hpp @@ -23,7 +23,7 @@ namespace urls { the functions @ref grammar::find_if and @ref grammar::find_if_not. @code - result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( reserved_chars ) ); + system::result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( reserved_chars ) ); @endcode @par Specification diff --git a/boost/url/rfc/sub_delim_chars.hpp b/boost/url/rfc/sub_delim_chars.hpp index c5b9714..cbda0e8 100644 --- a/boost/url/rfc/sub_delim_chars.hpp +++ b/boost/url/rfc/sub_delim_chars.hpp @@ -23,7 +23,7 @@ namespace urls { the functions @ref grammar::find_if and @ref grammar::find_if_not. @code - result< decode_view > = grammar::parse( "Program%20Files", pct_encoded_rule( sub_delim_chars ) ); + system::result< decode_view > = grammar::parse( "Program%20Files", pct_encoded_rule( sub_delim_chars ) ); @endcode @par BNF diff --git a/boost/url/rfc/unreserved_chars.hpp b/boost/url/rfc/unreserved_chars.hpp index 9f70b4c..b0fdf09 100644 --- a/boost/url/rfc/unreserved_chars.hpp +++ b/boost/url/rfc/unreserved_chars.hpp @@ -23,7 +23,7 @@ namespace urls { the functions @ref grammar::find_if and @ref grammar::find_if_not. @code - result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( unreserved_chars ) ); + system::result< decode_view > rv = grammar::parse( "Program%20Files", pct_encoded_rule( unreserved_chars ) ); @endcode @par BNF diff --git a/boost/url/rfc/uri_reference_rule.hpp b/boost/url/rfc/uri_reference_rule.hpp index fb99cf0..c617693 100644 --- a/boost/url/rfc/uri_reference_rule.hpp +++ b/boost/url/rfc/uri_reference_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< url_view > rv = grammar::parse( "ws://echo.example.com/?name=boost#demo", uri_reference_rule ); + system::result< url_view > rv = grammar::parse( "ws://echo.example.com/?name=boost#demo", uri_reference_rule ); @endcode @par BNF @@ -60,7 +60,7 @@ struct uri_reference_rule_t char const*& it, char const* end ) const noexcept -> - result; + system::result; }; constexpr uri_reference_rule_t uri_reference_rule{}; diff --git a/boost/url/rfc/uri_rule.hpp b/boost/url/rfc/uri_rule.hpp index 8e64918..9681e74 100644 --- a/boost/url/rfc/uri_rule.hpp +++ b/boost/url/rfc/uri_rule.hpp @@ -27,7 +27,7 @@ namespace urls { @par Example Rules are used with the function @ref grammar::parse. @code - result< url_view > rv = grammar::parse( "https://www.example.com/index.htm?id=guest#s1", uri_rule ); + system::result< url_view > rv = grammar::parse( "https://www.example.com/index.htm?id=guest#s1", uri_rule ); @endcode @par BNF @@ -57,7 +57,7 @@ struct uri_rule_t char const*& it, char const* const end ) const noexcept -> - result; + system::result; }; constexpr uri_rule_t uri_rule{}; diff --git a/boost/url/scheme.hpp b/boost/url/scheme.hpp index 59b53a6..fe730cd 100644 --- a/boost/url/scheme.hpp +++ b/boost/url/scheme.hpp @@ -11,7 +11,7 @@ #define BOOST_URL_SCHEME_HPP #include -#include +#include #include namespace boost { @@ -139,7 +139,7 @@ enum class scheme : unsigned short */ BOOST_URL_DECL scheme -string_to_scheme(string_view s) noexcept; +string_to_scheme(core::string_view s) noexcept; /** Return the normalized string for a known scheme @@ -148,7 +148,7 @@ string_to_scheme(string_view s) noexcept; @param s The known scheme constant */ BOOST_URL_DECL -string_view +core::string_view to_string(scheme s) noexcept; /** Return the default port for a known scheme diff --git a/boost/url/segments_encoded_view.hpp b/boost/url/segments_encoded_view.hpp index 06a5ba8..eeed98c 100644 --- a/boost/url/segments_encoded_view.hpp +++ b/boost/url/segments_encoded_view.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include @@ -165,7 +165,7 @@ public: */ BOOST_URL_DECL segments_encoded_view( - string_view s); + core::string_view s); /** Assignment @@ -230,8 +230,8 @@ public: BOOST_URL_DECL friend - result - parse_path(string_view s) noexcept; + system::result + parse_path(core::string_view s) noexcept; }; } // urls diff --git a/boost/url/segments_ref.hpp b/boost/url/segments_ref.hpp index eed2546..52d395a 100644 --- a/boost/url/segments_ref.hpp +++ b/boost/url/segments_ref.hpp @@ -203,7 +203,7 @@ public: BOOST_URL_DECL segments_ref& operator=(std::initializer_list< - string_view> init); + core::string_view> init); /** Conversion @@ -307,7 +307,7 @@ public: BOOST_URL_DECL void assign(std::initializer_list< - string_view> init); + core::string_view> init); /** Assign segments @@ -327,7 +327,7 @@ public: @par Mandates @code - std::is_convertible< std::iterator_traits< FwdIt >::reference_type, string_view >::value == true + std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true @endcode @par Complexity @@ -377,7 +377,7 @@ public: iterator insert( iterator before, - string_view s); + core::string_view s); /** Insert segments @@ -425,7 +425,7 @@ public: iterator insert( iterator before, - std::initializer_list init); + std::initializer_list init); /** Insert segments @@ -446,7 +446,7 @@ public: @par Mandates @code - std::is_convertible< std::iterator_traits< FwdIt >::reference_type, string_view >::value == true + std::is_convertible< std::iterator_traits< FwdIt >::reference_type, core::string_view >::value == true @endcode @par Complexity @@ -555,7 +555,7 @@ public: iterator replace( iterator pos, - string_view s); + core::string_view s); /** Replace segments @@ -586,7 +586,7 @@ public: replace( iterator from, iterator to, - string_view s); + core::string_view s); /** Replace segments @@ -627,7 +627,7 @@ public: iterator from, iterator to, std::initializer_list< - string_view> init); + core::string_view> init); /** Replace segments @@ -692,7 +692,7 @@ public: */ void push_back( - string_view s); + core::string_view s); /** Remove the last segment diff --git a/boost/url/segments_view.hpp b/boost/url/segments_view.hpp index ece9d28..a26425e 100644 --- a/boost/url/segments_view.hpp +++ b/boost/url/segments_view.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace boost { namespace urls { @@ -161,7 +161,7 @@ public: */ BOOST_URL_DECL segments_view( - string_view s); + core::string_view s); /** Assignment diff --git a/boost/url/src.hpp b/boost/url/src.hpp index 643798f..22dd88e 100644 --- a/boost/url/src.hpp +++ b/boost/url/src.hpp @@ -1,11 +1,8 @@ // -// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) +// Copyright (c) 2023 alandefreitas (alandefreitas@gmail.com) // -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/url +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt // #ifndef BOOST_URL_SRC_HPP @@ -13,108 +10,15 @@ /* -This file is meant to be included once, -in a translation unit of the program. +This file used to be used as a form of library integration +to allow the library to be compiled as a single target. + +This form of integration is discontinued. + +Please refer to the following link for instructions: +https://www.boost.org/doc/libs/master/libs/url/doc/html/url/overview.html */ +#error "src.hpp is discontinued and should not be used. Please use the compiled library instead." -// MUST COME FIRST -#ifndef BOOST_URL_SOURCE -#define BOOST_URL_SOURCE -#endif - -// We include this in case someone is -// using src.hpp as their main header file -#include - -//------------------------------------------------ -// -// url -// -//------------------------------------------------ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//------------------------------------------------ -// -// grammar -// -//------------------------------------------------ - -#include - -#include -#include -#include -#include -#include -#include - -//------------------------------------------------ -// -// rfc -// -//------------------------------------------------ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#endif +#endif \ No newline at end of file diff --git a/boost/url/static_url.hpp b/boost/url/static_url.hpp index b52b4b9..9bac261 100644 --- a/boost/url/static_url.hpp +++ b/boost/url/static_url.hpp @@ -49,7 +49,7 @@ class static_url; @li @ref parse_uri @li @ref parse_uri_reference */ -class BOOST_SYMBOL_VISIBLE +class BOOST_URL_DECL static_url_base : public url_base { @@ -57,13 +57,13 @@ class BOOST_SYMBOL_VISIBLE friend class static_url; ~static_url_base() = default; - BOOST_URL_DECL static_url_base( + static_url_base( char* buf, std::size_t cap) noexcept; - BOOST_URL_DECL static_url_base( - char* buf, std::size_t cap, string_view s); - BOOST_URL_DECL void clear_impl() noexcept override; - BOOST_URL_DECL void reserve_impl(std::size_t, op_t&) override; - BOOST_URL_DECL void cleanup(op_t&) override; + static_url_base( + char* buf, std::size_t cap, core::string_view s); + void clear_impl() noexcept override; + void reserve_impl(std::size_t, op_t&) override; + void cleanup(op_t&) override; void copy(url_view_base const& u) @@ -216,7 +216,7 @@ public: */ explicit static_url( - string_view s) + core::string_view s) : static_url_base( buf_, sizeof(buf_), s) { @@ -342,7 +342,7 @@ public: // /// @copydoc url_base::set_scheme - static_url& set_scheme(string_view s) { url_base::set_scheme(s); return *this; } + static_url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; } /// @copydoc url_base::set_scheme_id static_url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; } /// @copydoc url_base::remove_scheme @@ -354,28 +354,28 @@ public: static_url& remove_authority() { url_base::remove_authority(); return *this; } /// @copydoc url_base::set_userinfo - static_url& set_userinfo(string_view s) { url_base::set_userinfo(s); return *this; } + static_url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; } /// @copydoc url_base::set_encoded_userinfo static_url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; } /// @copydoc url_base::remove_userinfo static_url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; } /// @copydoc url_base::set_user - static_url& set_user(string_view s) { url_base::set_user(s); return *this; } + static_url& set_user(core::string_view s) { url_base::set_user(s); return *this; } /// @copydoc url_base::set_encoded_user static_url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; } /// @copydoc url_base::set_password - static_url& set_password(string_view s) { url_base::set_password(s); return *this; } + static_url& set_password(core::string_view s) { url_base::set_password(s); return *this; } /// @copydoc url_base::set_encoded_password static_url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; } /// @copydoc url_base::remove_password static_url& remove_password() noexcept { url_base::remove_password(); return *this; } /// @copydoc url_base::set_host - static_url& set_host(string_view s) { url_base::set_host(s); return *this; } + static_url& set_host(core::string_view s) { url_base::set_host(s); return *this; } /// @copydoc url_base::set_encoded_host static_url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; } /// @copydoc url_base::set_host_address - static_url& set_host_address(string_view s) { url_base::set_host_address(s); return *this; } + static_url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; } /// @copydoc url_base::set_encoded_host_address static_url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; } /// @copydoc url_base::set_host_ipv4 @@ -383,27 +383,27 @@ public: /// @copydoc url_base::set_host_ipv6 static_url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; } /// @copydoc url_base::set_host_ipvfuture - static_url& set_host_ipvfuture(string_view s) { url_base::set_host_ipvfuture(s); return *this; } + static_url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; } /// @copydoc url_base::set_host_name - static_url& set_host_name(string_view s) { url_base::set_host_name(s); return *this; } + static_url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; } /// @copydoc url_base::set_encoded_host_name static_url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; } /// @copydoc url_base::set_port_number static_url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; } /// @copydoc url_base::set_port - static_url& set_port(string_view s) { url_base::set_port(s); return *this; } + static_url& set_port(core::string_view s) { url_base::set_port(s); return *this; } /// @copydoc url_base::remove_port static_url& remove_port() noexcept { url_base::remove_port(); return *this; } /// @copydoc url_base::set_path_absolute //bool set_path_absolute(bool absolute); /// @copydoc url_base::set_path - static_url& set_path(string_view s) { url_base::set_path(s); return *this; } + static_url& set_path(core::string_view s) { url_base::set_path(s); return *this; } /// @copydoc url_base::set_encoded_path static_url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; } /// @copydoc url_base::set_query - static_url& set_query(string_view s) { url_base::set_query(s); return *this; } + static_url& set_query(core::string_view s) { url_base::set_query(s); return *this; } /// @copydoc url_base::set_encoded_query static_url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; } /// @copydoc url_base::remove_query @@ -412,7 +412,7 @@ public: /// @copydoc url_base::remove_fragment static_url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; } /// @copydoc url_base::set_fragment - static_url& set_fragment(string_view s) { url_base::set_fragment(s); return *this; } + static_url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; } /// @copydoc url_base::set_encoded_fragment static_url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; } diff --git a/boost/url/string_view.hpp b/boost/url/string_view.hpp index b59f291..1a7ff0f 100644 --- a/boost/url/string_view.hpp +++ b/boost/url/string_view.hpp @@ -25,8 +25,26 @@ namespace urls { ensuring that the lifetime of character buffer extends until it is no longer referenced. + + @note This alias is no longer supported and + should not be used in new code. Please use + `core::string_view` instead. + + This alias is included for backwards + compatibility with earlier versions of the + library. + + However, it will be removed in future releases, + and using it in new code is not recommended. + + Please use the updated version instead to + ensure compatibility with future versions of + the library. + */ -typedef boost::core::string_view string_view; +using string_view + BOOST_URL_DEPRECATED("Use core::string_view instead") = + boost::core::string_view; } // urls } // boost diff --git a/boost/url/url.hpp b/boost/url/url.hpp index 9af3592..f70c17a 100644 --- a/boost/url/url.hpp +++ b/boost/url/url.hpp @@ -60,7 +60,7 @@ namespace urls { @ref parse_uri_reference, @ref resolve. */ -class BOOST_SYMBOL_VISIBLE url +class BOOST_URL_DECL url : public url_base { friend std::hash; @@ -82,7 +82,6 @@ public: buffer is destroyed, invalidating all references to it. */ - BOOST_URL_DECL virtual ~url(); /** Constructor @@ -118,7 +117,6 @@ public: 4.2. Relative Reference (rfc3986) */ - BOOST_URL_DECL url() noexcept; /** Constructor @@ -168,9 +166,8 @@ public: @li 4.1. URI Reference */ - BOOST_URL_DECL explicit - url(string_view s); + url(core::string_view s); /** Constructor @@ -194,7 +191,6 @@ public: @param u The url to move from. */ - BOOST_URL_DECL url(url&& u) noexcept; /** Constructor @@ -272,7 +268,6 @@ public: @param u The url to assign from. */ - BOOST_URL_DECL url& operator=(url&& u) noexcept; @@ -362,7 +357,6 @@ public: @param other The object to swap with */ - BOOST_URL_DECL void swap(url& other) noexcept; @@ -412,7 +406,7 @@ public: // /// @copydoc url_base::set_scheme - url& set_scheme(string_view s) { url_base::set_scheme(s); return *this; } + url& set_scheme(core::string_view s) { url_base::set_scheme(s); return *this; } /// @copydoc url_base::set_scheme_id url& set_scheme_id(urls::scheme id) { url_base::set_scheme_id(id); return *this; } /// @copydoc url_base::remove_scheme @@ -424,28 +418,28 @@ public: url& remove_authority() { url_base::remove_authority(); return *this; } /// @copydoc url_base::set_userinfo - url& set_userinfo(string_view s) { url_base::set_userinfo(s); return *this; } + url& set_userinfo(core::string_view s) { url_base::set_userinfo(s); return *this; } /// @copydoc url_base::set_encoded_userinfo url& set_encoded_userinfo(pct_string_view s) { url_base::set_encoded_userinfo(s); return *this; } /// @copydoc url_base::remove_userinfo url& remove_userinfo() noexcept { url_base::remove_userinfo(); return *this; } /// @copydoc url_base::set_user - url& set_user(string_view s) { url_base::set_user(s); return *this; } + url& set_user(core::string_view s) { url_base::set_user(s); return *this; } /// @copydoc url_base::set_encoded_user url& set_encoded_user(pct_string_view s) { url_base::set_encoded_user(s); return *this; } /// @copydoc url_base::set_password - url& set_password(string_view s) { url_base::set_password(s); return *this; } + url& set_password(core::string_view s) { url_base::set_password(s); return *this; } /// @copydoc url_base::set_encoded_password url& set_encoded_password(pct_string_view s) { url_base::set_encoded_password(s); return *this; } /// @copydoc url_base::remove_password url& remove_password() noexcept { url_base::remove_password(); return *this; } /// @copydoc url_base::set_host - url& set_host(string_view s) { url_base::set_host(s); return *this; } + url& set_host(core::string_view s) { url_base::set_host(s); return *this; } /// @copydoc url_base::set_encoded_host url& set_encoded_host(pct_string_view s) { url_base::set_encoded_host(s); return *this; } /// @copydoc url_base::set_host_address - url& set_host_address(string_view s) { url_base::set_host_address(s); return *this; } + url& set_host_address(core::string_view s) { url_base::set_host_address(s); return *this; } /// @copydoc url_base::set_encoded_host_address url& set_encoded_host_address(pct_string_view s) { url_base::set_encoded_host_address(s); return *this; } /// @copydoc url_base::set_host_ipv4 @@ -453,31 +447,31 @@ public: /// @copydoc url_base::set_host_ipv6 url& set_host_ipv6(ipv6_address const& addr) { url_base::set_host_ipv6(addr); return *this; } /// @copydoc url_base::set_host_ipvfuture - url& set_host_ipvfuture(string_view s) { url_base::set_host_ipvfuture(s); return *this; } + url& set_host_ipvfuture(core::string_view s) { url_base::set_host_ipvfuture(s); return *this; } /// @copydoc url_base::set_host_name - url& set_host_name(string_view s) { url_base::set_host_name(s); return *this; } + url& set_host_name(core::string_view s) { url_base::set_host_name(s); return *this; } /// @copydoc url_base::set_encoded_host_name url& set_encoded_host_name(pct_string_view s) { url_base::set_encoded_host_name(s); return *this; } /// @copydoc url_base::set_port_number url& set_port_number(std::uint16_t n) { url_base::set_port_number(n); return *this; } /// @copydoc url_base::set_port - url& set_port(string_view s) { url_base::set_port(s); return *this; } + url& set_port(core::string_view s) { url_base::set_port(s); return *this; } /// @copydoc url_base::remove_port url& remove_port() noexcept { url_base::remove_port(); return *this; } /// @copydoc url_base::set_path_absolute //bool set_path_absolute(bool absolute); /// @copydoc url_base::set_path - url& set_path(string_view s) { url_base::set_path(s); return *this; } + url& set_path(core::string_view s) { url_base::set_path(s); return *this; } /// @copydoc url_base::set_encoded_path url& set_encoded_path(pct_string_view s) { url_base::set_encoded_path(s); return *this; } /// @copydoc url_base::set_query - url& set_query(string_view s) { url_base::set_query(s); return *this; } + url& set_query(core::string_view s) { url_base::set_query(s); return *this; } /// @copydoc url_base::set_encoded_query url& set_encoded_query(pct_string_view s) { url_base::set_encoded_query(s); return *this; } /// @copydoc url_base::set_params - url& set_params(std::initializer_list s) { url_base::set_params(s); return *this; } + url& set_params(std::initializer_list ps) { url_base::set_params(ps); return *this; } /// @copydoc url_base::set_encoded_params url& set_encoded_params(std::initializer_list< param_pct_view > ps) { url_base::set_encoded_params(ps); return *this; } /// @copydoc url_base::remove_query @@ -486,7 +480,7 @@ public: /// @copydoc url_base::remove_fragment url& remove_fragment() noexcept { url_base::remove_fragment(); return *this; } /// @copydoc url_base::set_fragment - url& set_fragment(string_view s) { url_base::set_fragment(s); return *this; } + url& set_fragment(core::string_view s) { url_base::set_fragment(s); return *this; } /// @copydoc url_base::set_encoded_fragment url& set_encoded_fragment(pct_string_view s) { url_base::set_encoded_fragment(s); return *this; } @@ -512,9 +506,9 @@ private: char* allocate(std::size_t); void deallocate(char* s); - BOOST_URL_DECL void clear_impl() noexcept override; - BOOST_URL_DECL void reserve_impl(std::size_t, op_t&) override; - BOOST_URL_DECL void cleanup(op_t&) override; + void clear_impl() noexcept override; + void reserve_impl(std::size_t, op_t&) override; + void cleanup(op_t&) override; }; } // urls diff --git a/boost/url/url_base.hpp b/boost/url/url_base.hpp index bb69592..5b20195 100644 --- a/boost/url/url_base.hpp +++ b/boost/url/url_base.hpp @@ -60,7 +60,7 @@ struct pattern; @li @ref parse_uri @li @ref parse_uri_reference */ -class BOOST_SYMBOL_VISIBLE +class BOOST_URL_DECL url_base : public url_view_base { @@ -79,27 +79,27 @@ class BOOST_SYMBOL_VISIBLE { ~op_t(); op_t(url_base&, - string_view* = nullptr, - string_view* = nullptr) noexcept; + core::string_view* = nullptr, + core::string_view* = nullptr) noexcept; void move(char*, char const*, std::size_t) noexcept; url_base& u; - string_view* s0 = nullptr; - string_view* s1 = nullptr; + core::string_view* s0 = nullptr; + core::string_view* s1 = nullptr; char* old = nullptr; }; virtual ~url_base() noexcept = default; url_base() noexcept = default; url_base(detail::url_impl const&) noexcept; - explicit url_base(string_view); - BOOST_URL_DECL void reserve_impl(std::size_t n); - BOOST_URL_DECL void copy(url_view_base const&); - BOOST_URL_DECL virtual void clear_impl() noexcept = 0; - BOOST_URL_DECL virtual void reserve_impl( + explicit url_base(core::string_view); + void reserve_impl(std::size_t n); + void copy(url_view_base const&); + virtual void clear_impl() noexcept = 0; + virtual void reserve_impl( std::size_t, op_t&) = 0; - BOOST_URL_DECL virtual void cleanup(op_t&) = 0; + virtual void cleanup(op_t&) = 0; public: //-------------------------------------------- @@ -239,9 +239,8 @@ public: @see @ref remove_scheme. */ - BOOST_URL_DECL url_base& - set_scheme(string_view s); + set_scheme(core::string_view s); /** Set the scheme @@ -274,7 +273,6 @@ public: @li 3.1. Scheme (rfc3986) */ - BOOST_URL_DECL url_base& #ifndef BOOST_URL_DOCS set_scheme_id(urls::scheme id); @@ -315,7 +313,6 @@ public: @see @ref set_scheme. */ - BOOST_URL_DECL url_base& remove_scheme(); @@ -361,7 +358,6 @@ public: @see @ref remove_authority. */ - BOOST_URL_DECL url_base& set_encoded_authority( pct_string_view s); @@ -404,7 +400,6 @@ public: @see @ref set_encoded_authority. */ - BOOST_URL_DECL url_base& remove_authority(); @@ -471,10 +466,9 @@ public: @ref remove_userinfo, @ref set_encoded_userinfo. */ - BOOST_URL_DECL url_base& set_userinfo( - string_view s); + core::string_view s); /** Set the userinfo. @@ -538,7 +532,6 @@ public: @ref remove_userinfo, @ref set_userinfo. */ - BOOST_URL_DECL url_base& set_encoded_userinfo( pct_string_view s); @@ -580,7 +573,6 @@ public: @ref set_encoded_userinfo, @ref set_userinfo. */ - BOOST_URL_DECL url_base& remove_userinfo() noexcept; @@ -630,10 +622,9 @@ public: @ref set_encoded_user, @ref set_password. */ - BOOST_URL_DECL url_base& set_user( - string_view s); + core::string_view s); /** Set the user @@ -684,7 +675,6 @@ public: @ref set_password, @ref set_user. */ - BOOST_URL_DECL url_base& set_encoded_user( pct_string_view s); @@ -737,10 +727,9 @@ public: @ref set_encoded_user, @ref set_user. */ - BOOST_URL_DECL url_base& set_password( - string_view s); + core::string_view s); /** Set the password. @@ -795,7 +784,6 @@ public: @ref set_encoded_user, @ref set_user. */ - BOOST_URL_DECL url_base& set_encoded_password( pct_string_view s); @@ -847,7 +835,6 @@ public: @ref set_password, @ref set_user. */ - BOOST_URL_DECL url_base& remove_password() noexcept; @@ -931,10 +918,9 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_host( - string_view s); + core::string_view s); /** Set the host @@ -1016,7 +1002,6 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_encoded_host(pct_string_view s); @@ -1115,9 +1100,8 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& - set_host_address(string_view s); + set_host_address(core::string_view s); /** Set the host to an address @@ -1219,7 +1203,6 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_encoded_host_address( pct_string_view s); @@ -1276,7 +1259,6 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_host_ipv4( ipv4_address const& addr); @@ -1341,7 +1323,6 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_host_ipv6( ipv6_address const& addr); @@ -1394,10 +1375,9 @@ public: @ref set_host_ipv6, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_host_ipvfuture( - string_view s); + core::string_view s); /** Set the host to a name @@ -1442,10 +1422,9 @@ public: @ref set_host_ipv6, @ref set_host_ipvfuture. */ - BOOST_URL_DECL url_base& set_host_name( - string_view s); + core::string_view s); /** Set the host to a name @@ -1496,7 +1475,6 @@ public: @ref set_host_ipvfuture, @ref set_host_name. */ - BOOST_URL_DECL url_base& set_encoded_host_name( pct_string_view s); @@ -1541,7 +1519,6 @@ public: @ref remove_port, @ref set_port. */ - BOOST_URL_DECL url_base& set_port_number(std::uint16_t n); @@ -1585,9 +1562,8 @@ public: @ref remove_port, @ref set_port. */ - BOOST_URL_DECL url_base& - set_port(string_view s); + set_port(core::string_view s); /** Remove the port @@ -1624,7 +1600,6 @@ public: @see @ref set_port. */ - BOOST_URL_DECL url_base& remove_port() noexcept; @@ -1687,7 +1662,6 @@ public: @ref set_encoded_path, @ref set_path. */ - BOOST_URL_DECL bool set_path_absolute(bool absolute); @@ -1703,6 +1677,14 @@ public: to ensure that no other parts of the url is semantically affected. + @note + This function does not encode '/' chars, which + are unreserved for paths but reserved for + path segments. If a path segment should include + encoded '/'s to differentiate it from path separators, + the functions @ref set_encoded_path or @ref segments + should be used instead. + @par Example @code url u( "http://www.example.com" ); @@ -1746,10 +1728,9 @@ public: @ref set_encoded_path, @ref set_path_absolute. */ - BOOST_URL_DECL url_base& set_path( - string_view s); + core::string_view s); /** Set the path. @@ -1812,7 +1793,6 @@ public: @ref set_path, @ref set_path_absolute. */ - BOOST_URL_DECL url_base& set_encoded_path( pct_string_view s); @@ -1868,7 +1848,6 @@ public: @ref set_path, @ref set_path_absolute. */ - BOOST_URL_DECL urls::segments_ref segments() noexcept; @@ -1930,7 +1909,6 @@ public: @ref set_path, @ref set_path_absolute. */ - BOOST_URL_DECL segments_encoded_ref encoded_segments() noexcept; @@ -1992,10 +1970,9 @@ public: @ref remove_query, @ref set_encoded_query. */ - BOOST_URL_DECL url_base& set_query( - string_view s); + core::string_view s); /** Set the query @@ -2048,7 +2025,6 @@ public: @ref remove_query, @ref set_query. */ - BOOST_URL_DECL url_base& set_encoded_query( pct_string_view s); @@ -2097,7 +2073,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL params_ref params() noexcept; @@ -2158,7 +2133,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL params_ref params(encoding_opts opt) noexcept; @@ -2213,7 +2187,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL params_encoded_ref encoded_params() noexcept; @@ -2267,7 +2240,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL url_base& set_params( std::initializer_list ps ) noexcept; @@ -2328,7 +2300,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL url_base& set_encoded_params( std::initializer_list< param_pct_view > ps ) noexcept; @@ -2371,7 +2342,6 @@ public: @ref set_encoded_query, @ref set_query. */ - BOOST_URL_DECL url_base& remove_query() noexcept; @@ -2417,7 +2387,6 @@ public: @ref set_encoded_fragment, @ref set_fragment. */ - BOOST_URL_DECL url_base& remove_fragment() noexcept; @@ -2462,10 +2431,9 @@ public: @ref remove_fragment, @ref set_encoded_fragment. */ - BOOST_URL_DECL url_base& set_fragment( - string_view s); + core::string_view s); /** Set the fragment. @@ -2514,7 +2482,6 @@ public: @ref remove_fragment, @ref set_fragment. */ - BOOST_URL_DECL url_base& set_encoded_fragment( pct_string_view s); @@ -2546,7 +2513,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL url_base& remove_origin(); @@ -2570,7 +2536,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize(); @@ -2590,7 +2555,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize_scheme(); @@ -2613,7 +2577,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize_authority(); @@ -2637,7 +2600,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize_path(); @@ -2660,7 +2622,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize_query(); @@ -2683,7 +2644,6 @@ public: >6.2.2 Syntax-Based Normalization (rfc3986) */ - BOOST_URL_DECL url_base& normalize_fragment(); @@ -2734,7 +2694,7 @@ public: If an error occurs, the contents of this URL are unspecified and a @ref result - with an @ref error_code is returned. + with an `system::error_code` is returned. @par Example @code @@ -2777,13 +2737,12 @@ public: @ref url, @ref url_view. */ - BOOST_URL_DECL - result + system::result resolve( url_view_base const& ref); friend - result + system::result resolve( url_view_base const& base, url_view_base const& ref, @@ -2803,17 +2762,17 @@ private: char* shrink_impl(int, std::size_t, op_t&); char* shrink_impl(int, int, std::size_t, op_t&); - void set_scheme_impl(string_view, urls::scheme); + void set_scheme_impl(core::string_view, urls::scheme); char* set_user_impl(std::size_t n, op_t& op); char* set_password_impl(std::size_t n, op_t& op); char* set_userinfo_impl(std::size_t n, op_t& op); char* set_host_impl(std::size_t n, op_t& op); char* set_port_impl(std::size_t n, op_t& op); + char* set_path_impl(std::size_t n, op_t& op); - string_view + core::string_view first_segment() const noexcept; - BOOST_URL_DECL detail::segments_iter_impl edit_segments( detail::segments_iter_impl const&, @@ -2821,7 +2780,6 @@ private: detail::any_segments_iter&& it0, int absolute = -1); - BOOST_URL_DECL auto edit_params( detail::params_iter_impl const&, @@ -2829,8 +2787,7 @@ private: detail::any_params_iter&&) -> detail::params_iter_impl; - BOOST_URL_DECL - result + system::result resolve_impl( url_view_base const& base, url_view_base const& ref); @@ -2886,7 +2843,7 @@ private: @par Example @code url dest; - error_code ec; + system::error_code ec; resolve("/one/two/three", "four", dest, ec); assert( dest.str() == "/one/two/four" ); @@ -2929,7 +2886,7 @@ private: @ref url_view. */ inline -result +system::result resolve( url_view_base const& base, url_view_base const& ref, diff --git a/boost/url/url_view.hpp b/boost/url/url_view.hpp index 1fca8a4..6a06420 100644 --- a/boost/url/url_view.hpp +++ b/boost/url/url_view.hpp @@ -24,7 +24,7 @@ namespace urls { strings constructed from a parsed, external character buffer whose storage is managed by the caller. That is, it acts like a - @ref string_view in terms of ownership. + `core::string_view` in terms of ownership. The caller is responsible for ensuring that the lifetime of the underlying character buffer extends until it is no @@ -48,7 +48,7 @@ namespace urls { contain an error. The error can be converted to an exception by the caller if desired: @code - result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" ); + system::result< url_view > rv = parse_uri_reference( "https://www.example.com/index.htm?text=none#a1" ); @endcode @par BNF @@ -71,7 +71,7 @@ namespace urls { @ref parse_uri, @ref parse_uri_reference. */ -class BOOST_SYMBOL_VISIBLE url_view +class BOOST_URL_DECL url_view : public url_view_base { friend std::hash; @@ -143,7 +143,6 @@ public: 4.2. Relative Reference (rfc3986) */ - BOOST_URL_DECL url_view() noexcept; /** Constructor @@ -195,18 +194,22 @@ public: @see @ref parse_uri_reference. */ - BOOST_URL_DECL - url_view(string_view s); + url_view(core::string_view s); - /// @copydoc url_view(string_view) + /// @copydoc url_view(core::string_view) template< class String #ifndef BOOST_URL_DOCS , class = typename std::enable_if< std::is_convertible< String, - string_view - >::value>::type + core::string_view + >::value && + !std::is_convertible< + String*, + url_view_base* + >::value + >::type #endif > url_view( @@ -257,7 +260,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL url_view( url_view_base const& other) noexcept; @@ -305,7 +307,6 @@ public: @par Exception Safety Throws nothing. */ - BOOST_URL_DECL url_view& operator=( url_view_base const& other) noexcept; diff --git a/boost/url/url_view_base.hpp b/boost/url/url_view_base.hpp index 88ccfc3..85798e7 100644 --- a/boost/url/url_view_base.hpp +++ b/boost/url/url_view_base.hpp @@ -62,7 +62,7 @@ struct pattern; @li @ref parse_uri @li @ref parse_uri_reference */ -class BOOST_SYMBOL_VISIBLE +class BOOST_URL_DECL url_view_base : private detail::parts_base { @@ -89,10 +89,8 @@ class BOOST_SYMBOL_VISIBLE struct shared_impl; - BOOST_URL_DECL url_view_base() noexcept; - BOOST_URL_DECL explicit url_view_base( detail::url_impl const&) noexcept; @@ -113,7 +111,6 @@ class BOOST_SYMBOL_VISIBLE #ifndef BOOST_URL_DOCS public: #endif - BOOST_URL_DECL std::size_t digest(std::size_t = 0) const noexcept; @@ -241,14 +238,14 @@ public: @par Exception Safety Throws nothing. */ - string_view + core::string_view buffer() const noexcept { - return string_view( + return core::string_view( data(), size()); } - /** Return the URL as a string_view + /** Return the URL as a core::string_view @par Complexity Constant. @@ -257,7 +254,7 @@ public: Throws nothing. */ - operator string_view() const noexcept + operator core::string_view() const noexcept { return buffer(); } @@ -297,7 +294,6 @@ public: @par Exception Safety Calls to allocate may throw. */ - BOOST_URL_DECL std::shared_ptr< url_view const> persist() const; @@ -340,7 +336,6 @@ public: @ref scheme, @ref scheme_id. */ - BOOST_URL_DECL bool has_scheme() const noexcept; @@ -377,8 +372,7 @@ public: @ref has_scheme, @ref scheme_id. */ - BOOST_URL_DECL - string_view + core::string_view scheme() const noexcept; /** Return the scheme @@ -427,7 +421,6 @@ public: @ref has_scheme, @ref scheme. */ - BOOST_URL_DECL urls::scheme scheme_id() const noexcept; @@ -519,7 +512,6 @@ public: @ref encoded_authority, @ref has_authority. */ - BOOST_URL_DECL authority_view authority() const noexcept; @@ -556,7 +548,6 @@ public: @ref authority, @ref has_authority. */ - BOOST_URL_DECL pct_string_view encoded_authority() const noexcept; @@ -603,7 +594,6 @@ public: @ref userinfo. */ - BOOST_URL_DECL bool has_userinfo() const noexcept; @@ -645,7 +635,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL bool has_password() const noexcept; @@ -754,7 +743,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_userinfo() const noexcept; @@ -853,7 +841,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_user() const noexcept; @@ -946,7 +933,6 @@ public: @ref user, @ref userinfo. */ - BOOST_URL_DECL pct_string_view encoded_password() const noexcept; @@ -1067,7 +1053,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host() const noexcept; @@ -1182,7 +1167,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host_address() const noexcept; @@ -1222,7 +1206,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL ipv4_address host_ipv4_address() const noexcept; @@ -1270,7 +1253,6 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL ipv6_address host_ipv6_address() const noexcept; @@ -1303,8 +1285,7 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL - string_view + core::string_view host_ipvfuture() const noexcept; /** Return the host name @@ -1384,10 +1365,91 @@ public: @li 3.2.2. Host (rfc3986) */ - BOOST_URL_DECL pct_string_view encoded_host_name() const noexcept; + /** Return the IPv6 Zone ID + + If the host type is @ref host_type::ipv6, + this function returns the Zone ID as + a string. Otherwise an empty string is returned. + Any percent-escapes in the string are + decoded first. + + @par Example + @code + assert( url_view( "http://[fe80::1%25eth0]/" ).zone_id() == "eth0" ); + @endcode + + @par Complexity + Linear in `this->encoded_zone_id().size()`. + + @par Exception Safety + Calls to allocate may throw. + + @par BNF + @code + host = IP-literal / IPv4address / reg-name + + IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]" + + ZoneID = 1*( unreserved / pct-encoded ) + + IPv6addrz = IPv6address "%25" ZoneID + @endcode + + @par Specification + @li Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers + */ + template + BOOST_URL_STRTOK_RETURN + zone_id( + BOOST_URL_STRTOK_ARG(token)) const + { + encoding_opts opt; + opt.space_as_plus = false; + return encoded_zone_id().decode( + opt, std::move(token)); + } + + /** Return the IPv6 Zone ID + + If the host type is @ref host_type::ipv6, + this function returns the Zone ID as + a string. Otherwise an empty string is returned. + The returned string may contain + percent escapes. + + @par Example + @code + assert( url_view( "http://[fe80::1%25eth0]/" ).encoded_zone_id() == "eth0" ); + @endcode + + @par Complexity + Constant. + + @par Exception Safety + Throws nothing. + + @par BNF + @code + host = IP-literal / IPv4address / reg-name + + IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]" + + ZoneID = 1*( unreserved / pct-encoded ) + + IPv6addrz = IPv6address "%25" ZoneID + @endcode + + @par Specification + @li Representing IPv6 Zone Identifiers in Address Literals and Uniform Resource Identifiers + */ + pct_string_view + encoded_zone_id() const noexcept; + //-------------------------------------------- // // Port @@ -1426,7 +1488,6 @@ public: @ref port, @ref port_number. */ - BOOST_URL_DECL bool has_port() const noexcept; @@ -1462,8 +1523,7 @@ public: @ref has_port, @ref port_number. */ - BOOST_URL_DECL - string_view + core::string_view port() const noexcept; /** Return the port @@ -1498,7 +1558,6 @@ public: @ref has_port, @ref port. */ - BOOST_URL_DECL std::uint16_t port_number() const noexcept; @@ -1654,7 +1713,6 @@ public: @ref path, @ref segments. */ - BOOST_URL_DECL pct_string_view encoded_path() const noexcept; @@ -1695,7 +1753,6 @@ public: @ref path, @ref segments_view. */ - BOOST_URL_DECL segments_view segments() const noexcept; @@ -1746,7 +1803,6 @@ public: @ref segments, @ref segments_encoded_view. */ - BOOST_URL_DECL segments_encoded_view encoded_segments() const noexcept; @@ -1793,7 +1849,6 @@ public: @ref params, @ref query. */ - BOOST_URL_DECL bool has_query() const noexcept; @@ -1895,7 +1950,6 @@ public: @ref params, @ref query. */ - BOOST_URL_DECL pct_string_view encoded_query() const noexcept; @@ -1940,11 +1994,9 @@ public: @ref has_query, @ref query. */ - BOOST_URL_DECL params_view params() const noexcept; - BOOST_URL_DECL params_view params(encoding_opts opt) const noexcept; @@ -1993,7 +2045,6 @@ public: @ref params, @ref query. */ - BOOST_URL_DECL params_encoded_view encoded_params() const noexcept; @@ -2036,7 +2087,6 @@ public: @ref encoded_fragment, @ref fragment. */ - BOOST_URL_DECL bool has_fragment() const noexcept; @@ -2141,7 +2191,6 @@ public: @ref fragment, @ref has_fragment. */ - BOOST_URL_DECL pct_string_view encoded_fragment() const noexcept; @@ -2187,7 +2236,6 @@ public: @ref port, @ref port_number. */ - BOOST_URL_DECL pct_string_view encoded_host_and_port() const noexcept; @@ -2216,7 +2264,6 @@ public: @ref encoded_resource, @ref encoded_target. */ - BOOST_URL_DECL pct_string_view encoded_origin() const noexcept; @@ -2249,7 +2296,6 @@ public: @ref encoded_origin, @ref encoded_target. */ - BOOST_URL_DECL pct_string_view encoded_resource() const noexcept; @@ -2282,7 +2328,6 @@ public: @ref encoded_origin, @ref encoded_resource. */ - BOOST_URL_DECL pct_string_view encoded_target() const noexcept; @@ -2311,7 +2356,6 @@ public: @return -1 if `*this < other`, 0 if `this == other`, and 1 if `this > other`. */ - BOOST_URL_DECL int compare(url_view_base const& other) const noexcept; @@ -2690,7 +2734,6 @@ private: // implementation // //-------------------------------------------- - BOOST_URL_DECL static int segments_compare( diff --git a/boost/url/variant.hpp b/boost/url/variant.hpp index 81d2c32..dbb2d04 100644 --- a/boost/url/variant.hpp +++ b/boost/url/variant.hpp @@ -19,7 +19,8 @@ namespace urls { /** The type of variant used by the library */ template -using variant = +using variant + BOOST_URL_DEPRECATED("Use variant2::variant instead") = boost::variant2::variant; } // urls diff --git a/boost/variant.hpp b/boost/variant.hpp deleted file mode 100644 index f179ccf..0000000 --- a/boost/variant.hpp +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant.hpp header file -// See http://www.boost.org/libs/variant for documentation. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_HPP -#define BOOST_VARIANT_HPP - -// variant "main" -#include -#include -#include - -// common applications -#include -#include -#include -#include - -#endif // BOOST_VARIANT_HPP diff --git a/boost/variant/apply_visitor.hpp b/boost/variant/apply_visitor.hpp deleted file mode 100644 index 6ad54fb..0000000 --- a/boost/variant/apply_visitor.hpp +++ /dev/null @@ -1,20 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/apply_visitor.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_APPLY_VISITOR_HPP -#define BOOST_VARIANT_APPLY_VISITOR_HPP - -#include -#include -#include - -#endif // BOOST_VARIANT_APPLY_VISITOR_HPP diff --git a/boost/variant/bad_visit.hpp b/boost/variant/bad_visit.hpp deleted file mode 100644 index 9396d08..0000000 --- a/boost/variant/bad_visit.hpp +++ /dev/null @@ -1,43 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/bad_visit.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_BAD_VISIT_HPP -#define BOOST_VARIANT_BAD_VISIT_HPP - -#include - -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// class bad_visit -// -// Exception thrown when a visitation attempt via apply_visitor fails due -// to invalid visited subtype or contents. -// -struct BOOST_SYMBOL_VISIBLE bad_visit - : std::exception -{ -public: // std::exception interface - - const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE - { - return "boost::bad_visit: " - "failed visitation using boost::apply_visitor"; - } - -}; - -} // namespace boost - -#endif // BOOST_VARIANT_BAD_VISIT_HPP diff --git a/boost/variant/detail/apply_visitor_binary.hpp b/boost/variant/detail/apply_visitor_binary.hpp deleted file mode 100644 index 10c2403..0000000 --- a/boost/variant/detail/apply_visitor_binary.hpp +++ /dev/null @@ -1,358 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/apply_visitor_binary.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 Eric Friedman -// Copyright (c) 2014-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP -#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP - -#include - -#include - -#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) -# include -#endif - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -# include -# include -# include -# include // for boost::move, boost::forward -#endif - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// function template apply_visitor(visitor, visitable1, visitable2) -// -// Visits visitable1 and visitable2 such that their values (which we -// shall call x and y, respectively) are used as arguments in the -// expression visitor(x, y). -// - -namespace detail { namespace variant { - -template -class apply_visitor_binary_invoke -{ -public: // visitor typedefs - - typedef typename Visitor::result_type - result_type; - -private: // representation - - Visitor& visitor_; - Value1& value1_; - -public: // structors - - apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT - : visitor_(visitor) - , value1_(value1) - { - } - -public: // visitor interfaces - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - - template - typename enable_if_c::value, result_type>::type - operator()(Value2&& value2) - { - return visitor_(::boost::move(value1_), ::boost::forward(value2)); - } - - template - typename disable_if_c::value, result_type>::type - operator()(Value2&& value2) - { - return visitor_(value1_, ::boost::forward(value2)); - } - -#else - - template - result_type - operator()(Value2& value2) - { - return visitor_(value1_, value2); - } - -#endif - -private: - apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&); -}; - -template -class apply_visitor_binary_unwrap -{ -public: // visitor typedefs - - typedef typename Visitor::result_type - result_type; - -private: // representation - - Visitor& visitor_; - Visitable2& visitable2_; - -public: // structors - - apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT - : visitor_(visitor) - , visitable2_(visitable2) - { - } - -public: // visitor interfaces - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - - template - typename enable_if_c::value, result_type>::type - operator()(Value1&& value1) - { - apply_visitor_binary_invoke< - Visitor - , Value1 - , ! ::boost::is_lvalue_reference::value - > invoker(visitor_, value1); - - return boost::apply_visitor(invoker, ::boost::move(visitable2_)); - } - - template - typename disable_if_c::value, result_type>::type - operator()(Value1&& value1) - { - apply_visitor_binary_invoke< - Visitor - , Value1 - , ! ::boost::is_lvalue_reference::value - > invoker(visitor_, value1); - - return boost::apply_visitor(invoker, visitable2_); - } - -#else - - template - result_type - operator()(Value1& value1) - { - apply_visitor_binary_invoke< - Visitor - , Value1 - , false - > invoker(visitor_, value1); - - return boost::apply_visitor(invoker, visitable2_); - } - -#endif - -private: - apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&); - -}; - -}} // namespace detail::variant - -// -// nonconst-visitor version: -// - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -template -inline typename Visitor::result_type -apply_visitor( Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap< - Visitor, Visitable2, ! ::boost::is_lvalue_reference::value - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, ::boost::forward(visitable1)); -} - -#else - -template -inline typename Visitor::result_type -apply_visitor( Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap< - Visitor, Visitable2, false - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, visitable1); -} - -#endif - -// -// const-visitor version: -// - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -template -inline typename Visitor::result_type -apply_visitor( const Visitor& visitor , Visitable1&& visitable1 , Visitable2&& visitable2) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap< - const Visitor, Visitable2, ! ::boost::is_lvalue_reference::value - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, ::boost::forward(visitable1)); -} - -#else - -template -inline typename Visitor::result_type -apply_visitor( const Visitor& visitor , Visitable1& visitable1 , Visitable2& visitable2) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap< - const Visitor, Visitable2, false - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, visitable1); -} - -#endif - - -#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) - -////////////////////////////////////////////////////////////////////////// -// function template apply_visitor(visitor, visitable1, visitable2) -// -// C++14 part. -// - -namespace detail { namespace variant { - -template -class apply_visitor_binary_invoke_cpp14 -{ - Visitor& visitor_; - Value1& value1_; - -public: // structors - - apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT - : visitor_(visitor) - , value1_(value1) - { - } - -public: // visitor interfaces - - template - decltype(auto) operator()(Value2&& value2, typename enable_if_c::value, bool>::type = true) - { - return visitor_(::boost::move(value1_), ::boost::forward(value2)); - } - - template - decltype(auto) operator()(Value2&& value2, typename disable_if_c::value, bool>::type = true) - { - return visitor_(value1_, ::boost::forward(value2)); - } - -private: - apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&); -}; - -template -class apply_visitor_binary_unwrap_cpp14 -{ - Visitor& visitor_; - Visitable2& visitable2_; - -public: // structors - - apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT - : visitor_(visitor) - , visitable2_(visitable2) - { - } - -public: // visitor interfaces - - template - decltype(auto) operator()(Value1&& value1, typename enable_if_c::value, bool>::type = true) - { - apply_visitor_binary_invoke_cpp14< - Visitor - , Value1 - , ! ::boost::is_lvalue_reference::value - > invoker(visitor_, value1); - - return boost::apply_visitor(invoker, ::boost::move(visitable2_)); - } - - template - decltype(auto) operator()(Value1&& value1, typename disable_if_c::value, bool>::type = true) - { - apply_visitor_binary_invoke_cpp14< - Visitor - , Value1 - , ! ::boost::is_lvalue_reference::value - > invoker(visitor_, value1); - - return boost::apply_visitor(invoker, visitable2_); - } - -private: - apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&); -}; - -}} // namespace detail::variant - -template -inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2, - typename boost::disable_if< - boost::detail::variant::has_result_type, - bool - >::type = true) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14< - Visitor, Visitable2, ! ::boost::is_lvalue_reference::value - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, ::boost::forward(visitable1)); -} - -template -inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1&& visitable1, Visitable2&& visitable2, - typename boost::disable_if< - boost::detail::variant::has_result_type, - bool - >::type = true) -{ - ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14< - const Visitor, Visitable2, ! ::boost::is_lvalue_reference::value - > unwrapper(visitor, visitable2); - - return boost::apply_visitor(unwrapper, ::boost::forward(visitable1)); -} - - -#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP diff --git a/boost/variant/detail/apply_visitor_delayed.hpp b/boost/variant/detail/apply_visitor_delayed.hpp deleted file mode 100644 index 0a90062..0000000 --- a/boost/variant/detail/apply_visitor_delayed.hpp +++ /dev/null @@ -1,146 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/apply_visitor_delayed.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP -#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP - -#include -#include -#include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES - - -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// function template apply_visitor(visitor) -// -// Returns a function object, overloaded for unary and binary usage, that -// visits its arguments using visitor (or a copy of visitor) via -// * apply_visitor( visitor, [argument] ) -// under unary invocation, or -// * apply_visitor( visitor, [argument1], [argument2] ) -// under binary invocation. -// -// NOTE: Unlike other apply_visitor forms, the visitor object must be -// non-const; this prevents user from giving temporary, to disastrous -// effect (i.e., returned function object would have dead reference). -// - -template -class apply_visitor_delayed_t -{ -public: // visitor typedefs - - typedef typename Visitor::result_type - result_type; - -private: // representation - - Visitor& visitor_; - -public: // structors - - explicit apply_visitor_delayed_t(Visitor& visitor) BOOST_NOEXCEPT - : visitor_(visitor) - { - } - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -public: // N-ary visitor interface - template - result_type operator()(Visitables&... visitables) const - { - return apply_visitor(visitor_, visitables...); - } - -#else // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -public: // unary visitor interface - - template - result_type operator()(Visitable& visitable) const - { - return apply_visitor(visitor_, visitable); - } - -public: // binary visitor interface - - template - result_type operator()(Visitable1& visitable1, Visitable2& visitable2) const - { - return apply_visitor(visitor_, visitable1, visitable2); - } - -#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -private: - apply_visitor_delayed_t& operator=(const apply_visitor_delayed_t&); - -}; - -template -inline typename boost::enable_if< - boost::detail::variant::has_result_type, - apply_visitor_delayed_t - >::type apply_visitor(Visitor& visitor) -{ - return apply_visitor_delayed_t(visitor); -} - -#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) \ - && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -template -class apply_visitor_delayed_cpp14_t -{ -private: // representation - Visitor& visitor_; - -public: // structors - - explicit apply_visitor_delayed_cpp14_t(Visitor& visitor) BOOST_NOEXCEPT - : visitor_(visitor) - { - } - -public: // N-ary visitor interface - template - decltype(auto) operator()(Visitables&... visitables) const - { - return apply_visitor(visitor_, visitables...); - } - -private: - apply_visitor_delayed_cpp14_t& operator=(const apply_visitor_delayed_cpp14_t&); - -}; - -template -inline typename boost::disable_if< - boost::detail::variant::has_result_type, - apply_visitor_delayed_cpp14_t - >::type apply_visitor(Visitor& visitor) -{ - return apply_visitor_delayed_cpp14_t(visitor); -} - -#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) - // && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP diff --git a/boost/variant/detail/apply_visitor_unary.hpp b/boost/variant/detail/apply_visitor_unary.hpp deleted file mode 100644 index 7574b44..0000000 --- a/boost/variant/detail/apply_visitor_unary.hpp +++ /dev/null @@ -1,145 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/apply_visitor_unary.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 Eric Friedman -// Copyright (c) 2014-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP -#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP - -#include -#include - -#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) -# include -# include -# include -# include -# include -# include -# include -# include -# include -#endif - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// function template apply_visitor(visitor, visitable) -// -// Visits visitable with visitor. -// - -// -// nonconst-visitor version: -// - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -template -inline typename Visitor::result_type -apply_visitor(Visitor& visitor, Visitable&& visitable) -{ - return ::boost::forward(visitable).apply_visitor(visitor); -} -#else -template -inline typename Visitor::result_type -apply_visitor(Visitor& visitor, Visitable& visitable) -{ - return visitable.apply_visitor(visitor); -} -#endif - -// -// const-visitor version: -// - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -template -inline typename Visitor::result_type -apply_visitor(const Visitor& visitor, Visitable&& visitable) -{ - return ::boost::forward(visitable).apply_visitor(visitor); -} -#else -template -inline typename Visitor::result_type -apply_visitor(const Visitor& visitor, Visitable& visitable) -{ - return visitable.apply_visitor(visitor); -} -#endif - - -#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) -#define BOOST_VARIANT_HAS_DECLTYPE_APPLY_VISITOR_RETURN_TYPE - -// C++14 -namespace detail { namespace variant { - -// This class serves only metaprogramming purposes. none of its methods must be called at runtime! -template -struct result_multideduce1 { - typedef typename remove_reference::type::types types; - typedef typename boost::mpl::begin::type begin_it; - typedef typename boost::mpl::advance< - begin_it, boost::mpl::int_::type::value - 1> - >::type last_it; - - template // avoid explicit specialization in class scope - struct deduce_impl { - typedef typename boost::mpl::next::type next_t; - typedef typename boost::mpl::deref::type value_t; - typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() ) - : boost::declval< typename deduce_impl::type >()) type; - }; - - template - struct deduce_impl { - typedef typename boost::mpl::deref::type value_t; - typedef decltype(boost::declval< Visitor& >()( boost::declval< copy_cv_ref_t< value_t, Variant > >() )) type; - }; - - typedef typename deduce_impl::type type; -}; - -template -struct result_wrapper1 -{ - typedef typename result_multideduce1::type result_type; - - Visitor&& visitor_; - explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT - : visitor_(::boost::forward(visitor)) - {} - - template - result_type operator()(T&& val) const { - return visitor_(::boost::forward(val)); - } -}; - -}} // namespace detail::variant - -template -inline decltype(auto) apply_visitor(Visitor&& visitor, Visitable&& visitable, - typename boost::disable_if< - boost::detail::variant::has_result_type, - bool - >::type = true) -{ - boost::detail::variant::result_wrapper1 cpp14_vis(::boost::forward(visitor)); - return ::boost::forward(visitable).apply_visitor(cpp14_vis); -} - -#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP diff --git a/boost/variant/detail/backup_holder.hpp b/boost/variant/detail/backup_holder.hpp deleted file mode 100644 index c11f12c..0000000 --- a/boost/variant/detail/backup_holder.hpp +++ /dev/null @@ -1,95 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/backup_holder.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP -#define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP - -#include -#include - -namespace boost { -namespace detail { namespace variant { - -template -class backup_holder -{ -private: // representation - - T* backup_; - -public: // structors - - ~backup_holder() BOOST_NOEXCEPT - { - delete backup_; - } - - explicit backup_holder(T* backup) BOOST_NOEXCEPT - : backup_(backup) - { - } - - backup_holder(const backup_holder&); - -public: // modifiers - - backup_holder& operator=(const backup_holder& rhs) - { - *backup_ = rhs.get(); - return *this; - } - - backup_holder& operator=(const T& rhs) - { - *backup_ = rhs; - return *this; - } - - void swap(backup_holder& rhs) BOOST_NOEXCEPT - { - T* tmp = rhs.backup_; - rhs.backup_ = this->backup_; - this->backup_ = tmp; - } - -public: // queries - - T& get() BOOST_NOEXCEPT - { - return *backup_; - } - - const T& get() const BOOST_NOEXCEPT - { - return *backup_; - } - -}; - -template -backup_holder::backup_holder(const backup_holder&) - : backup_(0) -{ - // not intended for copy, but do not want to prohibit syntactically - BOOST_ASSERT(false); -} - -template -void swap(backup_holder& lhs, backup_holder& rhs) BOOST_NOEXCEPT -{ - lhs.swap(rhs); -} - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP diff --git a/boost/variant/detail/cast_storage.hpp b/boost/variant/detail/cast_storage.hpp deleted file mode 100644 index 0320278..0000000 --- a/boost/variant/detail/cast_storage.hpp +++ /dev/null @@ -1,42 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/cast_storage.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP -#define BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP - -#include - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) function template cast_storage -// -// Casts the given storage to the specified type, but with qualification. -// - -template -inline T& cast_storage(void* storage) -{ - return *static_cast(storage); -} - -template -inline const T& cast_storage(const void* storage) -{ - return *static_cast(storage); -} - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP diff --git a/boost/variant/detail/config.hpp b/boost/variant/detail/config.hpp deleted file mode 100644 index da76fe2..0000000 --- a/boost/variant/detail/config.hpp +++ /dev/null @@ -1,19 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/config.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 Eric Friedman -// Copyright (c) 2016-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_CONFIG_HPP -#define BOOST_VARIANT_DETAIL_CONFIG_HPP - -#include -#include - -#endif // BOOST_VARIANT_DETAIL_CONFIG_HPP diff --git a/boost/variant/detail/element_index.hpp b/boost/variant/detail/element_index.hpp deleted file mode 100644 index 06cf06d..0000000 --- a/boost/variant/detail/element_index.hpp +++ /dev/null @@ -1,63 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/element_index.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2014-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP -#define BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP - -#include -#include -#include - -#include -#include -#include - -namespace boost { namespace detail { namespace variant { - -template -struct variant_element_functor : - boost::mpl::or_< - boost::is_same, - boost::is_same >, - boost::is_same - > -{}; - -template -struct element_iterator_impl : - boost::mpl::find_if< - Types, - boost::mpl::or_< - variant_element_functor, - variant_element_functor::type > - > - > -{}; - -template -struct element_iterator : - element_iterator_impl< typename Variant::types, typename boost::remove_reference::type > -{}; - -template -struct holds_element : - boost::mpl::not_< - boost::is_same< - typename boost::mpl::end::type, - typename element_iterator::type - > - > -{}; - - -}}} // namespace boost::detail::variant - -#endif // BOOST_VARIANT_DETAIL_ELEMENT_INDEX_HPP diff --git a/boost/variant/detail/enable_recursive.hpp b/boost/variant/detail/enable_recursive.hpp deleted file mode 100644 index 757e0df..0000000 --- a/boost/variant/detail/enable_recursive.hpp +++ /dev/null @@ -1,133 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/enable_recursive.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP -#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP - -#include -#include - -#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) -# include -# include -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace boost { -namespace detail { namespace variant { - -#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -# define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(T,Dest,Source) \ - substitute< T , Dest , Source > \ - /**/ - -#else // defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class template rebind1 -// -// Limited workaround in case 'substitute' metafunction unavailable. -// - -template -struct rebind1 -{ -private: - typedef typename mpl::lambda< - mpl::identity - >::type le_; - -public: - typedef typename mpl::eval_if< - is_same< le_, mpl::identity > - , le_ // identity - , mpl::apply1 - >::type type; -}; - -# define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL(T,Dest,Source) \ - rebind1< T , Dest > \ - /**/ - -#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction enable_recursive -// -// See boost/variant/detail/enable_recursive_fwd.hpp for more information. -// - - -template -struct enable_recursive - : BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL( - T, RecursiveVariant, ::boost::recursive_variant_ - ) -{ -}; - -template -struct enable_recursive< T,RecursiveVariant,mpl::false_ > -{ -private: // helpers, for metafunction result (below) - - typedef typename BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL( - T, RecursiveVariant, ::boost::recursive_variant_ - )::type t_; - -public: // metafunction result - - // [Wrap with recursive_wrapper only if rebind really changed something:] - typedef typename mpl::if_< - mpl::or_< - is_same< t_,T > - , is_reference - , is_pointer - > - , t_ - , boost::recursive_wrapper - >::type type; - -}; - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction class quoted_enable_recursive -// -// Same behavior as enable_recursive metafunction (see above). -// -template -struct quoted_enable_recursive -{ - template - struct apply - : enable_recursive - { - }; -}; - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_HPP diff --git a/boost/variant/detail/enable_recursive_fwd.hpp b/boost/variant/detail/enable_recursive_fwd.hpp deleted file mode 100644 index cac156b..0000000 --- a/boost/variant/detail/enable_recursive_fwd.hpp +++ /dev/null @@ -1,87 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/enable_recursive_fwd.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP -#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP - -#include - -#include - -# include - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) tag recursive_flag -// -// Signifies that the variant should perform recursive substituion. -// - - -template -struct recursive_flag -{ - typedef T type; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_recursive_flag -// -// Signifies that the variant should perform recursive substituion. -// - - -template -struct is_recursive_flag - : mpl::false_ -{ -}; - -template -struct is_recursive_flag< recursive_flag > - : mpl::true_ -{ -}; - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction enable_recursive -// -// Attempts recursive_variant_ tag substitution, wrapping with -// boost::recursive_wrapper if substituion occurs w/ non-indirect result -// (i.e., not a reference or pointer) *and* NoWrapper is false_. -// -template < - typename T - , typename RecursiveVariant - , typename NoWrapper = mpl::false_ - > -struct enable_recursive; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction class quoted_enable_recursive -// -// Same behavior as enable_recursive metafunction (see above). -// -template < - typename RecursiveVariant - , typename NoWrapper = mpl::false_ - > -struct quoted_enable_recursive; - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP diff --git a/boost/variant/detail/forced_return.hpp b/boost/variant/detail/forced_return.hpp deleted file mode 100644 index 6d8911b..0000000 --- a/boost/variant/detail/forced_return.hpp +++ /dev/null @@ -1,52 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/forced_return.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 Eric Friedman -// Copyright (c) 2015-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP -#define BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP - -#include -#include - - -#ifdef BOOST_MSVC -# pragma warning( push ) -# pragma warning( disable : 4702 ) // unreachable code -#endif - -namespace boost { namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) function template forced_return -// -// Logical error to permit invocation at runtime, but (artificially) satisfies -// compile-time requirement of returning a result value. -// -template -BOOST_NORETURN inline T -forced_return() -{ - // logical error: should never be here! (see above) - BOOST_ASSERT(false); - - T (*dummy)() = 0; - (void)dummy; - BOOST_UNREACHABLE_RETURN(dummy()); -} - -}}} // namespace boost::detail::variant - - -#ifdef BOOST_MSVC -# pragma warning( pop ) -#endif - -#endif // BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP diff --git a/boost/variant/detail/has_result_type.hpp b/boost/variant/detail/has_result_type.hpp deleted file mode 100644 index e1ca5b4..0000000 --- a/boost/variant/detail/has_result_type.hpp +++ /dev/null @@ -1,37 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/has_result_type.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2014-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP -#define BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP - -#include -#include - - -namespace boost { namespace detail { namespace variant { - -template -struct has_result_type { -private: - typedef char yes; - typedef struct { char array[2]; } no; - - template static yes test(typename boost::remove_reference::type*); - template static no test(...); - -public: - BOOST_STATIC_CONSTANT(bool, value = sizeof(test(0)) == sizeof(yes)); -}; - -}}} // namespace boost::detail::variant - -#endif // BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP - diff --git a/boost/variant/detail/hash_variant.hpp b/boost/variant/detail/hash_variant.hpp deleted file mode 100644 index 4eb8377..0000000 --- a/boost/variant/detail/hash_variant.hpp +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/hash_variant.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2011-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_HASH_VARIANT_FUNCTION_HPP -#define BOOST_HASH_VARIANT_FUNCTION_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include -#include -#include - -namespace boost { - - namespace detail { namespace variant { - struct variant_hasher: public boost::static_visitor { - template - std::size_t operator()(T const& val) const { - boost::hash hasher; - return hasher(val); - } - }; - }} - - template < BOOST_VARIANT_ENUM_PARAMS(typename T) > - std::size_t hash_value(variant< BOOST_VARIANT_ENUM_PARAMS(T) > const& val) { - std::size_t seed = boost::apply_visitor(detail::variant::variant_hasher(), val); - hash_combine(seed, val.which()); - return seed; - } -} - -#endif - diff --git a/boost/variant/detail/initializer.hpp b/boost/variant/detail/initializer.hpp deleted file mode 100644 index 4a54c27..0000000 --- a/boost/variant/detail/initializer.hpp +++ /dev/null @@ -1,249 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/initializer.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_INITIALIZER_HPP -#define BOOST_VARIANT_DETAIL_INITIALIZER_HPP - -#include // for placement new - -#include - -#include -#include -#include -#include - -#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) -# include -# include -# include -# include -# include -# include -# include -#else -# include -# include -# include -# include -#endif - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) support to simulate standard overload resolution rules -// -// The below initializers allows variant to follow standard overload -// resolution rules over the specified set of bounded types. -// -// On compilers where using declarations in class templates can correctly -// avoid name hiding, use an optimal solution based on the variant's typelist. -// -// Otherwise, use a preprocessor workaround based on knowledge of the fixed -// size of the variant's psuedo-variadic template parameter list. -// - -#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - -// (detail) quoted metafunction make_initializer_node -// -// Exposes a pair whose first type is a node in the initializer hierarchy. -// -struct make_initializer_node -{ - template - struct apply - { - private: // helpers, for metafunction result (below) - - typedef typename BaseIndexPair::first - base; - typedef typename BaseIndexPair::second - index; - - class initializer_node - : public base - { - private: // helpers, for static functions (below) - - typedef typename mpl::deref::type - recursive_enabled_T; - typedef typename unwrap_recursive::type - public_T; - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - typedef boost::is_reference - is_reference_content_t; - - typedef typename boost::mpl::if_::type - param_T; - - template struct disable_overload{}; - - typedef typename boost::mpl::if_, public_T&& >::type - param2_T; -#else - typedef typename call_traits::param_type - param_T; -#endif - - public: // static functions - - using base::initialize; - - static int initialize(void* dest, param_T operand) - { - typedef typename boost::detail::make_reference_content< - recursive_enabled_T - >::type internal_T; - - new(dest) internal_T(operand); - return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - static int initialize(void* dest, param2_T operand) - { - // This assert must newer trigger, because all the reference contents are - // handled by the initilize(void* dest, param_T operand) function above - BOOST_ASSERT(!is_reference_content_t::value); - - typedef typename boost::mpl::if_::type value_T; - new(dest) value_T( boost::detail::variant::move(operand) ); - return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which - } -#endif - }; - - friend class initializer_node; - - public: // metafunction result - - typedef mpl::pair< - initializer_node - , typename mpl::next< index >::type - > type; - - }; -}; - -// (detail) class initializer_root -// -// Every level of the initializer hierarchy must expose the name -// "initialize," so initializer_root provides a dummy function: -// -class initializer_root -{ -public: // static functions - - static void initialize(); - -}; - -#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - - // Obsolete. Remove. - #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \ - BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \ - /**/ - - // Obsolete. Remove. - #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \ - typedef typename unwrap_recursive< \ - BOOST_PP_CAT(recursive_enabled_T,N) \ - >::type BOOST_PP_CAT(public_T,N); \ - typedef typename call_traits< \ - BOOST_PP_CAT(public_T,N) \ - >::param_type BOOST_PP_CAT(param_T,N); \ - /**/ - -template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) > -struct preprocessor_list_initializer -{ -public: // static functions - - #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \ - typedef typename unwrap_recursive< \ - BOOST_PP_CAT(recursive_enabled_T,N) \ - >::type BOOST_PP_CAT(public_T,N); \ - typedef typename call_traits< \ - BOOST_PP_CAT(public_T,N) \ - >::param_type BOOST_PP_CAT(param_T,N); \ - static int initialize( \ - void* dest \ - , BOOST_PP_CAT(param_T,N) operand \ - ) \ - { \ - typedef typename boost::detail::make_reference_content< \ - BOOST_PP_CAT(recursive_enabled_T,N) \ - >::type internal_T; \ - \ - new(dest) internal_T(operand); \ - return (N); /*which*/ \ - } \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION - , _ - ) - - #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION - -}; - -#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround - -}} // namespace detail::variant -} // namespace boost - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_AUX_INITIALIZER_T -// -// Given both the variant's typelist and a basename for forming the list of -// bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer -// most appropriate to the current compiler. -// - -#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - -#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ - ::boost::mpl::iter_fold< \ - mpl_seq \ - , ::boost::mpl::pair< \ - ::boost::detail::variant::initializer_root \ - , ::boost::mpl::int_<0> \ - > \ - , ::boost::mpl::protect< \ - ::boost::detail::variant::make_initializer_node \ - > \ - >::type::first \ - /**/ - -#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - - // Obsolete. Remove. - #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \ - BOOST_VARIANT_ENUM_PARAMS(typename_base) \ - /**/ - -#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \ - ::boost::detail::variant::preprocessor_list_initializer< \ - BOOST_VARIANT_ENUM_PARAMS(typename_base) \ - > \ - /**/ - -#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround - -#endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP diff --git a/boost/variant/detail/make_variant_list.hpp b/boost/variant/detail/make_variant_list.hpp deleted file mode 100644 index bd78615..0000000 --- a/boost/variant/detail/make_variant_list.hpp +++ /dev/null @@ -1,73 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/make_variant_list.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 Eric Friedman, Itay Maman -// Copyright (c) 2013-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP -#define BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP - -#include - -#include -#include -#include - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction make_variant_list -// -// Provides a MPL-compatible sequence with the specified non-void types -// as arguments. -// -// Rationale: see class template convert_void (variant_fwd.hpp) and using- -// declaration workaround (below). -// - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -template < typename... T > -struct make_variant_list -{ - typedef typename mpl::list< T... >::type type; -}; - -#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -template < BOOST_VARIANT_ENUM_PARAMS(typename T) > -struct make_variant_list -{ -public: // metafunction result - - // [Define a macro to convert any void(NN) tags to mpl::void...] -# define BOOST_VARIANT_AUX_CONVERT_VOID(z, N,_) \ - typename convert_void< BOOST_PP_CAT(T,N) >::type - - // [...so that the specified types can be passed to mpl::list...] - typedef typename mpl::list< - BOOST_PP_ENUM( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_CONVERT_VOID - , _ - ) - >::type type; - - // [...and, finally, the conversion macro can be undefined:] -# undef BOOST_VARIANT_AUX_CONVERT_VOID - -}; - -#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP diff --git a/boost/variant/detail/move.hpp b/boost/variant/detail/move.hpp deleted file mode 100644 index 5866138..0000000 --- a/boost/variant/detail/move.hpp +++ /dev/null @@ -1,50 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/move.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 Eric Friedman -// Copyright (c) 2002 by Andrei Alexandrescu -// Copyright (c) 2013-2023 Antony Polukhin -// -// Use, modification and distribution are subject to the -// Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// This file derivative of MoJO. Much thanks to Andrei for his initial work. -// See for information on MOJO. -// Re-issued here under the Boost Software License, with permission of the original -// author (Andrei Alexandrescu). - - -#ifndef BOOST_VARIANT_DETAIL_MOVE_HPP -#define BOOST_VARIANT_DETAIL_MOVE_HPP - -#include -#include -#include // for boost::move -#include - -namespace boost { namespace detail { namespace variant { - -using boost::move; - -////////////////////////////////////////////////////////////////////////// -// function template move_swap -// -// Swaps using Koenig lookup but falls back to move-swap for primitive -// types and on non-conforming compilers. -// - -template -inline void move_swap(T& lhs, T& rhs) -{ - ::boost::adl_move_swap(lhs, rhs); -} - -}}} // namespace boost::detail::variant - -#endif // BOOST_VARIANT_DETAIL_MOVE_HPP - - - diff --git a/boost/variant/detail/multivisitors_cpp11_based.hpp b/boost/variant/detail/multivisitors_cpp11_based.hpp deleted file mode 100644 index a29e220..0000000 --- a/boost/variant/detail/multivisitors_cpp11_based.hpp +++ /dev/null @@ -1,217 +0,0 @@ -// Boost.Varaint -// Contains multivisitors that are implemented via variadic templates and std::tuple -// -// See http://www.boost.org for most recent version, including documentation. -// -// Copyright Antony Polukhin, 2013-2014. -// -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). - -#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP -#define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -#include -#include -#include - -#if defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_HDR_TUPLE) -# error "This file requires and variadic templates support" -#endif - -#include - -namespace boost { - -namespace detail { namespace variant { - - // Implementing some of the C++14 features in C++11 - template class index_sequence {}; - - template - struct make_index_sequence - : make_index_sequence - {}; - template - struct make_index_sequence<0, I...> - : index_sequence - {}; - - template - struct MoveableWrapper //Just a reference with some metadata - { - typedef T_ T; - static constexpr bool MoveSemantics = MoveSemantics_; - - T& v; - }; - - template - MoveableWrapper - wrap(Tp& t) - { - return MoveableWrapper{t}; - } - - template - typename enable_if_c::type - unwrap(Wrapper& w) - { - return ::boost::move(w.v); - } - - template - typename disable_if_c::type & - unwrap(Wrapper& w) - { - return w.v; - } - - // Implementing some of the helper tuple methods - template - std::tuple::type...> - tuple_tail_impl(const Tuple& tpl, index_sequence) - { - return std::tuple< - typename std::tuple_element::type... - > (std::get(tpl)...); - } - - template - std::tuple tuple_tail(const std::tuple& tpl) - { - return tuple_tail_impl(tpl, make_index_sequence()); - } - - - // Forward declaration - template - class one_by_one_visitor_and_value_referer; - - template - inline one_by_one_visitor_and_value_referer - make_one_by_one_visitor_and_value_referer( - Visitor& visitor, Visitables visitables, std::tuple values - ) - { - return one_by_one_visitor_and_value_referer ( - visitor, visitables, values - ); - } - - template - class one_by_one_visitor_and_value_referer - { - Visitor& visitor_; - std::tuple values_; - Visitables visitables_; - - public: // structors - one_by_one_visitor_and_value_referer( - Visitor& visitor, Visitables visitables, std::tuple values - ) BOOST_NOEXCEPT - : visitor_(visitor) - , values_(values) - , visitables_(visitables) - {} - - public: // visitor interfaces - typedef typename Visitor::result_type result_type; - - template - result_type operator()(Value&& value) const - { - return ::boost::apply_visitor( - make_one_by_one_visitor_and_value_referer( - visitor_, - tuple_tail(visitables_), - std::tuple_cat(values_, std::make_tuple(wrap::value>(value))) - ) - , unwrap(std::get<0>(visitables_)) // getting Head element - ); - } - - private: - one_by_one_visitor_and_value_referer& operator=(const one_by_one_visitor_and_value_referer&); - }; - - template - class one_by_one_visitor_and_value_referer, Values...> - { - Visitor& visitor_; - std::tuple values_; - - public: - one_by_one_visitor_and_value_referer( - Visitor& visitor, std::tuple<> /*visitables*/, std::tuple values - ) BOOST_NOEXCEPT - : visitor_(visitor) - , values_(values) - {} - - typedef typename Visitor::result_type result_type; - - template - result_type do_call(Tuple t, index_sequence) const { - return visitor_(unwrap(std::get(t))...); - } - - template - result_type operator()(Value&& value) const - { - return do_call( - std::tuple_cat(values_, std::make_tuple(wrap::value>(value))), - make_index_sequence() - ); - } - }; - -}} // namespace detail::variant - - template - inline typename Visitor::result_type - apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn) - { - return ::boost::apply_visitor( - ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( - visitor, - std::make_tuple( - ::boost::detail::variant::wrap::value>(v2), - ::boost::detail::variant::wrap::value>(v3), - ::boost::detail::variant::wrap::value>(vn)... - ), - std::tuple<>() - ), - ::boost::forward(v1) - ); - } - - template - inline typename Visitor::result_type - apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn) - { - return ::boost::apply_visitor( - ::boost::detail::variant::make_one_by_one_visitor_and_value_referer( - visitor, - std::make_tuple( - ::boost::detail::variant::wrap::value>(v2), - ::boost::detail::variant::wrap::value>(v3), - ::boost::detail::variant::wrap::value>(vn)... - ), - std::tuple<>() - ), - ::boost::forward(v1) - ); - } - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP11_BASED_HPP - diff --git a/boost/variant/detail/multivisitors_cpp14_based.hpp b/boost/variant/detail/multivisitors_cpp14_based.hpp deleted file mode 100644 index 4bbf81b..0000000 --- a/boost/variant/detail/multivisitors_cpp14_based.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// Boost.Varaint -// Contains multivisitors that are implemented via variadic templates, std::tuple -// and decltype(auto) -// -// See http://www.boost.org for most recent version, including documentation. -// -// Copyright Antony Polukhin, 2013-2014. -// -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). - -#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP -#define BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include - -namespace boost { - -namespace detail { namespace variant { - - // Forward declaration - template - class one_by_one_visitor_and_value_referer_cpp14; - - template - inline one_by_one_visitor_and_value_referer_cpp14 - make_one_by_one_visitor_and_value_referer_cpp14( - Visitor& visitor, Visitables visitables, std::tuple values - ) - { - return one_by_one_visitor_and_value_referer_cpp14 ( - visitor, visitables, values - ); - } - - template - class one_by_one_visitor_and_value_referer_cpp14 - { - Visitor& visitor_; - std::tuple values_; - Visitables visitables_; - - public: // structors - one_by_one_visitor_and_value_referer_cpp14( - Visitor& visitor, Visitables visitables, std::tuple values - ) BOOST_NOEXCEPT - : visitor_(visitor) - , values_(values) - , visitables_(visitables) - {} - - public: // visitor interfaces - template - decltype(auto) operator()(Value&& value) const - { - return ::boost::apply_visitor( - make_one_by_one_visitor_and_value_referer_cpp14( - visitor_, - tuple_tail(visitables_), - std::tuple_cat(values_, std::make_tuple(wrap::value>(value))) - ) - , unwrap(std::get<0>(visitables_)) // getting Head element - ); - } - - private: - one_by_one_visitor_and_value_referer_cpp14& operator=(const one_by_one_visitor_and_value_referer_cpp14&); - }; - - template - class one_by_one_visitor_and_value_referer_cpp14, Values...> - { - Visitor& visitor_; - std::tuple values_; - - public: - one_by_one_visitor_and_value_referer_cpp14( - Visitor& visitor, std::tuple<> /*visitables*/, std::tuple values - ) BOOST_NOEXCEPT - : visitor_(visitor) - , values_(values) - {} - - template - decltype(auto) do_call(Tuple t, index_sequence) const { - return visitor_(unwrap(std::get(t))...); - } - - template - decltype(auto) operator()(Value&& value) const - { - return do_call( - std::tuple_cat(values_, std::make_tuple(wrap::value>(value))), - make_index_sequence() - ); - } - }; - -}} // namespace detail::variant - - template - inline decltype(auto) apply_visitor(const Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn, - typename boost::disable_if< - boost::detail::variant::has_result_type, - bool - >::type = true) - { - return boost::apply_visitor( - ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14( - visitor, - std::make_tuple( - ::boost::detail::variant::wrap::value>(v2), - ::boost::detail::variant::wrap::value>(v3), - ::boost::detail::variant::wrap::value>(vn)... - ), - std::tuple<>() - ), - ::boost::forward(v1) - ); - } - - - template - inline decltype(auto) apply_visitor(Visitor& visitor, T1&& v1, T2&& v2, T3&& v3, TN&&... vn, - typename boost::disable_if< - boost::detail::variant::has_result_type, - bool - >::type = true) - { - return ::boost::apply_visitor( - ::boost::detail::variant::make_one_by_one_visitor_and_value_referer_cpp14( - visitor, - std::make_tuple( - ::boost::detail::variant::wrap::value>(v2), - ::boost::detail::variant::wrap::value>(v3), - ::boost::detail::variant::wrap::value>(vn)... - ), - std::tuple<>() - ), - ::boost::forward(v1) - ); - } - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_CPP14_BASED_HPP - diff --git a/boost/variant/detail/multivisitors_preprocessor_based.hpp b/boost/variant/detail/multivisitors_preprocessor_based.hpp deleted file mode 100644 index aa85a55..0000000 --- a/boost/variant/detail/multivisitors_preprocessor_based.hpp +++ /dev/null @@ -1,143 +0,0 @@ -// Boost.Varaint -// Contains multivisitors that are implemented via preprocessor magic -// -// See http://www.boost.org for most recent version, including documentation. -// -// Copyright Antony Polukhin, 2013-2014. -// -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). - -#ifndef BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP -#define BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include - -#include -#include -#include -#include - -#ifndef BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS -# define BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS 4 -#endif - -namespace boost { - -namespace detail { namespace variant { - - template - struct two_variables_holder { - private: - VisitorT& visitor_; - Visitable1T& visitable1_; - Visitable2T& visitable2_; - - // required to suppress warnings and ensure that we do not copy - // this visitor - two_variables_holder& operator=(const two_variables_holder&); - - public: - typedef BOOST_DEDUCED_TYPENAME VisitorT::result_type result_type; - - explicit two_variables_holder(VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2) BOOST_NOEXCEPT - : visitor_(visitor) - , visitable1_(visitable1) - , visitable2_(visitable2) - {} - -#define BOOST_VARIANT_OPERATOR_BEG() \ - return ::boost::apply_visitor( \ - ::boost::bind(boost::ref(visitor_), _1, _2 \ - /**/ - -#define BOOST_VARIANT_OPERATOR_END() \ - ), visitable1_, visitable2_); \ - /**/ - -#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \ - BOOST_PP_COMMA() boost::ref( BOOST_PP_CAT(vis, n) ) \ - /**/ - -#define BOOST_VARIANT_VISIT(z, n, data) \ - template \ - result_type operator()( \ - BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 1), VisitableUnwrapped, & vis) \ - ) const \ - { \ - BOOST_VARIANT_OPERATOR_BEG() \ - BOOST_PP_REPEAT(BOOST_PP_ADD(n, 1), BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \ - BOOST_VARIANT_OPERATOR_END() \ - } \ - /**/ - -BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, ~) -#undef BOOST_VARIANT_OPERATOR_BEG -#undef BOOST_VARIANT_OPERATOR_END -#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER -#undef BOOST_VARIANT_VISIT - - }; - - template - inline two_variables_holder make_two_variables_holder( - VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2 - ) BOOST_NOEXCEPT - { - return two_variables_holder(visitor, visitable1, visitable2); - } - - template - inline two_variables_holder make_two_variables_holder( - const VisitorT& visitor, Visitable1T& visitable1, Visitable2T& visitable2 - ) BOOST_NOEXCEPT - { - return two_variables_holder(visitor, visitable1, visitable2); - } - -}} // namespace detail::variant - -#define BOOST_VARIANT_APPLY_VISITOR_BEG() \ - return ::boost::apply_visitor( \ - boost::detail::variant::make_two_variables_holder(visitor, var0 , var1), \ - var2 \ - /**/ - -#define BOOST_VARIANT_APPLY_VISITOR_END() \ - ); \ - /**/ - -#define BOOST_VARANT_VISITORS_VARIABLES_PRINTER(z, n, data) \ - BOOST_PP_COMMA() BOOST_PP_CAT(var, BOOST_PP_ADD(n, 3)) \ - /**/ - -#define BOOST_VARIANT_VISIT(z, n, data) \ - template \ - inline BOOST_DEDUCED_TYPENAME Visitor::result_type apply_visitor( \ - data BOOST_PP_COMMA() BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ADD(n, 3), T, & var) \ - ) \ - { \ - BOOST_VARIANT_APPLY_VISITOR_BEG() \ - BOOST_PP_REPEAT(n, BOOST_VARANT_VISITORS_VARIABLES_PRINTER, ~) \ - BOOST_VARIANT_APPLY_VISITOR_END() \ - } \ - /**/ - -BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, const Visitor& visitor) -BOOST_PP_REPEAT( BOOST_PP_SUB(BOOST_VARAINT_MAX_MULTIVIZITOR_PARAMS, 2), BOOST_VARIANT_VISIT, Visitor& visitor) - -#undef BOOST_VARIANT_APPLY_VISITOR_BEG -#undef BOOST_VARIANT_APPLY_VISITOR_END -#undef BOOST_VARANT_VISITORS_VARIABLES_PRINTER -#undef BOOST_VARIANT_VISIT - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_MULTIVISITORS_PREPROCESSOR_BASED_HPP - diff --git a/boost/variant/detail/over_sequence.hpp b/boost/variant/detail/over_sequence.hpp deleted file mode 100644 index 48394f0..0000000 --- a/boost/variant/detail/over_sequence.hpp +++ /dev/null @@ -1,58 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/over_sequence.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Portions Copyright (C) 2002 David Abrahams -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP -#define BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP - -#include - - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class over_sequence -// -// Wrapper used to indicate bounded types for variant are from type sequence. -// -template -struct over_sequence -{ - typedef Types type; -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_over_sequence (modeled on code by David Abrahams) -// -// Indicates whether the specified type is of form over_sequence<...> or not. -// - - -template -struct is_over_sequence - : mpl::false_ -{ -}; - -template -struct is_over_sequence< over_sequence > - : mpl::true_ -{ -}; - - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP diff --git a/boost/variant/detail/std_hash.hpp b/boost/variant/detail/std_hash.hpp deleted file mode 100644 index 3e05c5c..0000000 --- a/boost/variant/detail/std_hash.hpp +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/std_hash.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2018-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_VARIANT_DETAIL_STD_HASH_HPP -#define BOOST_VARIANT_DETAIL_STD_HASH_HPP - -#include -#ifdef BOOST_HAS_PRAGMA_ONCE -# pragma once -#endif - -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH -// -// Define this macro if you do not wish to have a std::hash specialization for -// boost::variant. - -#if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) - -#include // for std::hash - -namespace std { - template < BOOST_VARIANT_ENUM_PARAMS(typename T) > - struct hash > { - std::size_t operator()(const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& val) const { - return ::boost::hash_value(val); - } - }; -} - -#endif // #if !defined(BOOST_VARIANT_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) - -#endif // BOOST_VARIANT_DETAIL_STD_HASH_HPP - diff --git a/boost/variant/detail/substitute.hpp b/boost/variant/detail/substitute.hpp deleted file mode 100644 index f9d29a5..0000000 --- a/boost/variant/detail/substitute.hpp +++ /dev/null @@ -1,279 +0,0 @@ - -#if !defined(BOOST_PP_IS_ITERATING) - -///// header body - -//----------------------------------------------------------------------------- -// boost variant/detail/substitute.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP -#define BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP - -#include - -#include -#include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { -namespace detail { namespace variant { - -#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction substitute -// -// Substitutes one type for another in the given type expression. -// - -// -// primary template -// -template < - typename T, typename Dest, typename Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM( - typename Arity /* = ... (see substitute_fwd.hpp) */ - ) - > -struct substitute -{ - typedef T type; -}; - -// -// tag substitution specializations -// - -#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(CV_) \ - template \ - struct substitute< \ - CV_ Source \ - , Dest \ - , Source \ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) \ - > \ - { \ - typedef CV_ Dest type; \ - }; \ - /**/ - -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG( BOOST_PP_EMPTY() ) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(const) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(volatile) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG(const volatile) - -#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_SUBSTITUTE_TAG - -// -// pointer specializations -// -#define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(CV_) \ - template \ - struct substitute< \ - T * CV_ \ - , Dest \ - , Source \ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) \ - > \ - { \ - typedef typename substitute< \ - T, Dest, Source \ - >::type * CV_ type; \ - }; \ - /**/ - -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER( BOOST_PP_EMPTY() ) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(const) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(volatile) -BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER(const volatile) - -#undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_IMPL_HANDLE_POINTER - -// -// reference specializations -// -template -struct substitute< - T& - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) - > -{ - typedef typename substitute< - T, Dest, Source - >::type & type; -}; - -// -// template expression (i.e., F<...>) specializations -// - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) -template < - template class F - , typename... Ts - , typename Dest - , typename Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) - > -struct substitute< - F - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) - > -{ - typedef F::type...> type; -}; - -// -// function specializations -// -template < - typename R - , typename... A - , typename Dest - , typename Source - > -struct substitute< - R (*)(A...) - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) - > -{ -private: - typedef typename substitute< R, Dest, Source >::type r; - -public: - typedef r (*type)(typename substitute< - A, Dest, Source - >::type...); -}; -#else - -#define BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL(N) \ - typedef typename substitute< \ - BOOST_PP_CAT(U,N), Dest, Source \ - >::type BOOST_PP_CAT(u,N); \ - /**/ - -#define BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF(z, N, _) \ - BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL( BOOST_PP_INC(N) ) \ - /**/ - -#define BOOST_PP_ITERATION_LIMITS (0,BOOST_MPL_LIMIT_METAFUNCTION_ARITY) -#define BOOST_PP_FILENAME_1 -#include BOOST_PP_ITERATE() - -#undef BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF_IMPL -#undef BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF - -#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) -#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_SUBSTITUTE_HPP - -///// iteration, depth == 1 - -#elif BOOST_PP_ITERATION_DEPTH() == 1 -#define i BOOST_PP_FRAME_ITERATION(1) - -#if i > 0 - -// -// template specializations -// -template < - template < BOOST_MPL_PP_PARAMS(i,typename P) > class T - , BOOST_MPL_PP_PARAMS(i,typename U) - , typename Dest - , typename Source - > -struct substitute< - T< BOOST_MPL_PP_PARAMS(i,U) > - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<( i )>) - > -{ -private: - BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF, _) - -public: - typedef T< BOOST_MPL_PP_PARAMS(i,u) > type; -}; - -// -// function specializations -// -template < - typename R - , BOOST_MPL_PP_PARAMS(i,typename U) - , typename Dest - , typename Source - > -struct substitute< - R (*)( BOOST_MPL_PP_PARAMS(i,U) ) - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) - > -{ -private: - typedef typename substitute< R, Dest, Source >::type r; - BOOST_MPL_PP_REPEAT(i, BOOST_VARIANT_AUX_SUBSTITUTE_TYPEDEF, _) - -public: - typedef r (*type)( BOOST_MPL_PP_PARAMS(i,u) ); -}; - -#elif i == 0 - -// -// zero-arg function specialization -// -template < - typename R, typename Dest, typename Source - > -struct substitute< - R (*)( void ) - , Dest - , Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(mpl::int_<-1>) - > -{ -private: - typedef typename substitute< R, Dest, Source >::type r; - -public: - typedef r (*type)( void ); -}; - -#endif // i - -#undef i -#endif // BOOST_PP_IS_ITERATING diff --git a/boost/variant/detail/substitute_fwd.hpp b/boost/variant/detail/substitute_fwd.hpp deleted file mode 100644 index cc49074..0000000 --- a/boost/variant/detail/substitute_fwd.hpp +++ /dev/null @@ -1,58 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/substitute_fwd.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP -#define BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP - -#include -#include -#include - - -/////////////////////////////////////////////////////////////////////////////// -// BOOST_VARIANT_DETAIL_NO_SUBSTITUTE -// -// Defined if 'substitute' is not implementable on the current compiler. -// - -#include -#include - -#if defined(BOOST_NO_TEMPLATE_TEMPLATE_PARAMETERS) \ - && !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) -# define BOOST_VARIANT_DETAIL_NO_SUBSTITUTE -#endif - -namespace boost { -namespace detail { namespace variant { - -#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -/////////////////////////////////////////////////////////////////////////////// -// metafunction substitute -// -// Substitutes one type for another in the given type expression. -// -template < - typename T, typename Dest, typename Source - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM( - typename Arity = mpl::int_< mpl::aux::template_arity::value > - ) - > -struct substitute; - -#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -}} // namespace detail::variant -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP diff --git a/boost/variant/detail/variant_io.hpp b/boost/variant/detail/variant_io.hpp deleted file mode 100644 index 63df74f..0000000 --- a/boost/variant/detail/variant_io.hpp +++ /dev/null @@ -1,95 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/variant_io.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_VARIANT_IO_HPP -#define BOOST_VARIANT_DETAIL_VARIANT_IO_HPP - -#include // for std::basic_ostream forward declare - -#include - -#include -#include - -namespace boost { - -/////////////////////////////////////////////////////////////////////////////// -// function template operator<< -// -// Outputs the content of the given variant to the given ostream. -// - -// forward declare (allows output of embedded variant< variant< ... >, ... >) -template < - BOOST_TEMPLATED_STREAM_ARGS(E,T) - BOOST_TEMPLATED_STREAM_COMMA - BOOST_VARIANT_ENUM_PARAMS(typename U) - > -inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<( - BOOST_TEMPLATED_STREAM(ostream, E,T)& out - , const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs - ); - -namespace detail { namespace variant { - -template -class printer - : public boost::static_visitor<> -{ -private: // representation - - OStream& out_; - -public: // structors - - explicit printer(OStream& out) - : out_( out ) - { - } - -public: // visitor interface - - template - void operator()(const T& operand) const - { - out_ << operand; - } - -private: - printer& operator=(const printer&); - -}; - -}} // namespace detail::variant - -template < - BOOST_TEMPLATED_STREAM_ARGS(E,T) - BOOST_TEMPLATED_STREAM_COMMA - BOOST_VARIANT_ENUM_PARAMS(typename U) - > -inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<( - BOOST_TEMPLATED_STREAM(ostream, E,T)& out - , const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs - ) -{ - detail::variant::printer< - BOOST_TEMPLATED_STREAM(ostream, E,T) - > visitor(out); - - rhs.apply_visitor(visitor); - - return out; -} - -} // namespace boost - -#endif // BOOST_VARIANT_DETAIL_VARIANT_IO_HPP diff --git a/boost/variant/detail/visitation_impl.hpp b/boost/variant/detail/visitation_impl.hpp deleted file mode 100644 index c3d91b8..0000000 --- a/boost/variant/detail/visitation_impl.hpp +++ /dev/null @@ -1,277 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/detail/visitation_impl.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP -#define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP - -#include - -#include -#include -#include -#include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -# pragma warning (push) -# pragma warning (disable : 4702) //unreachable code -#endif - -/////////////////////////////////////////////////////////////////////////////// -// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT -// -// Unrolls variant's visitation mechanism to reduce template instantiation -// and potentially increase runtime performance. (TODO: Investigate further.) -// -#if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) - -#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -# include -# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \ - BOOST_MPL_LIMIT_LIST_SIZE -#else -# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \ - BOOST_VARIANT_LIMIT_TYPES -#endif - -#endif - -// Define a compiler generic null pointer value -#if defined(BOOST_NO_CXX11_NULLPTR) -#define BOOST_VARIANT_NULL 0 -#else -#define BOOST_VARIANT_NULL nullptr -#endif - -namespace boost { -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class apply_visitor_unrolled -// -// Tag type indicates when visitation_impl is unrolled. -// -struct apply_visitor_unrolled {}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class template visitation_impl_step -// -// "Never ending" iterator range facilitates visitation_impl unrolling. -// - - -template -struct visitation_impl_step -{ - typedef typename mpl::deref::type type; - - typedef typename mpl::next::type next_iter; - typedef visitation_impl_step< - next_iter, LastIter - > next; -}; - -template -struct visitation_impl_step< LastIter,LastIter > -{ - typedef apply_visitor_unrolled type; - typedef visitation_impl_step next; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) function template visitation_impl_invoke -// -// Invokes the given visitor on the specified type in the given storage. -// - -template -inline typename Visitor::result_type -visitation_impl_invoke_impl( - int, Visitor& visitor, VoidPtrCV storage, T* - , mpl::true_// never_uses_backup - ) -{ - return visitor.internal_visit( - cast_storage(storage), 1L - ); -} - -template -inline typename Visitor::result_type -visitation_impl_invoke_impl( - int internal_which, Visitor& visitor, VoidPtrCV storage, T* - , mpl::false_// never_uses_backup - ) -{ - if (internal_which >= 0) - { - return visitor.internal_visit( - cast_storage(storage), 1L - ); - } - else - { - return visitor.internal_visit( - cast_storage< backup_holder >(storage), 1L - ); - } -} - -template -inline typename Visitor::result_type -visitation_impl_invoke( - int internal_which, Visitor& visitor, VoidPtrCV storage, T* t - , NoBackupFlag - , int - ) -{ - typedef typename mpl::or_< - NoBackupFlag - , is_nothrow_move_constructible - , has_nothrow_copy - >::type never_uses_backup; - - return (visitation_impl_invoke_impl)( - internal_which, visitor, storage, t - , never_uses_backup() - ); -} - -template -inline typename Visitor::result_type -visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long) -{ - // should never be here at runtime! - typedef typename Visitor::result_type result_type; - return ::boost::detail::variant::forced_return< result_type >(); -} - -/////////////////////////////////////////////////////////////////////////////// -// (detail) function template visitation_impl -// -// Invokes the given visitor on the type in the given variant storage. -// - -template < - typename W, typename S - , typename Visitor, typename VPCV - , typename NBF - > -inline typename Visitor::result_type -visitation_impl( - int, int, Visitor&, VPCV - , mpl::true_ // is_apply_visitor_unrolled - , NBF, W* = BOOST_VARIANT_NULL, S* = BOOST_VARIANT_NULL - ) -{ - // should never be here at runtime! - typedef typename Visitor::result_type result_type; - return ::boost::detail::variant::forced_return< result_type >(); -} - -template < - typename Which, typename step0 - , typename Visitor, typename VoidPtrCV - , typename NoBackupFlag - > -BOOST_FORCEINLINE typename Visitor::result_type -visitation_impl( - const int internal_which, const int logical_which - , Visitor& visitor, VoidPtrCV storage - , mpl::false_ // is_apply_visitor_unrolled - , NoBackupFlag no_backup_flag - , Which* = BOOST_VARIANT_NULL, step0* = BOOST_VARIANT_NULL - ) -{ - // Typedef apply_visitor_unrolled steps and associated types... -# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \ - typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \ - typedef typename BOOST_PP_CAT(step,N)::next \ - BOOST_PP_CAT(step, BOOST_PP_INC(N)); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_VISITATION_UNROLLING_LIMIT - , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF - , _ - ) - -# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF - - // ...switch on the target which-index value... - switch (logical_which) - { - - // ...applying the appropriate case: -# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \ - case (Which::value + (N)): \ - return (visitation_impl_invoke)( \ - internal_which, visitor, storage \ - , static_cast(0) \ - , no_backup_flag, 1L \ - ); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_VISITATION_UNROLLING_LIMIT - , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE - , _ - ) - -# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE - - default: break; - } - - // If not handled in this iteration, continue unrolling: - typedef mpl::int_< - Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) - > next_which; - - typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT) - next_step; - - typedef typename next_step::type next_type; - typedef typename is_same< next_type,apply_visitor_unrolled >::type - is_apply_visitor_unrolled; - - return detail::variant::visitation_impl( - internal_which, logical_which - , visitor, storage - , is_apply_visitor_unrolled() - , no_backup_flag - , static_cast(0), static_cast(0) - ); -} - -}} // namespace detail::variant -} // namespace boost - -#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -# pragma warning(pop) -#endif - -#endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP diff --git a/boost/variant/get.hpp b/boost/variant/get.hpp deleted file mode 100644 index 62fca60..0000000 --- a/boost/variant/get.hpp +++ /dev/null @@ -1,388 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/get.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 Eric Friedman, Itay Maman -// Copyright (c) 2014-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_GET_HPP -#define BOOST_VARIANT_GET_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { - -#if defined(BOOST_CLANG) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wweak-vtables" -#endif -////////////////////////////////////////////////////////////////////////// -// class bad_get -// -// The exception thrown in the event of a failed get of a value. -// -class BOOST_SYMBOL_VISIBLE bad_get - : public std::exception -{ -public: // std::exception implementation - - const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE - { - return "boost::bad_get: " - "failed value get using boost::get"; - } - -}; -#if defined(BOOST_CLANG) -# pragma clang diagnostic pop -#endif - - -////////////////////////////////////////////////////////////////////////// -// function template get -// -// Retrieves content of given variant object if content is of type T. -// Otherwise: pointer ver. returns 0; reference ver. throws bad_get. -// - -namespace detail { namespace variant { - -// (detail) class template get_visitor -// -// Generic static visitor that: if the value is of the specified type, -// returns a pointer to the value it visits; else a null pointer. -// -template -struct get_visitor -{ -private: // private typedefs - - typedef typename add_pointer::type pointer; - typedef typename add_reference::type reference; - -public: // visitor typedefs - - typedef pointer result_type; - -public: // visitor interfaces - - pointer operator()(reference operand) const BOOST_NOEXCEPT - { - return boost::addressof(operand); - } - - template - pointer operator()(const U&) const BOOST_NOEXCEPT - { - return static_cast(0); - } -}; - -}} // namespace detail::variant - -#ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE -# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) -# else -# if defined(BOOST_NO_CXX11_NULLPTR) -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ - , t* = 0 -# else -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ - , t* = nullptr -# endif -# endif -#endif - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// relaxed_get(variant) methods -// -template -inline - typename add_pointer::type -relaxed_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - typedef typename add_pointer::type U_ptr; - if (!operand) return static_cast(0); - - detail::variant::get_visitor v; - return operand->apply_visitor(v); -} - -template -inline - typename add_pointer::type -relaxed_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - typedef typename add_pointer::type U_ptr; - if (!operand) return static_cast(0); - - detail::variant::get_visitor v; - return operand->apply_visitor(v); -} - -template -inline - typename add_reference::type -relaxed_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - typedef typename add_pointer::type U_ptr; - U_ptr result = relaxed_get(boost::addressof(operand)); - - if (!result) - boost::throw_exception(bad_get()); - return *result; -} - -template -inline - typename add_reference::type -relaxed_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - typedef typename add_pointer::type U_ptr; - U_ptr result = relaxed_get(boost::addressof(operand)); - - if (!result) - boost::throw_exception(bad_get()); - return *result; -} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -#if defined(BOOST_MSVC) && (_MSC_VER < 1900) // MSVC-2014 has fixed the incorrect diagnostics. -# pragma warning(push) -# pragma warning(disable: 4172) // returning address of local variable or temporary -#endif - -template -inline - U&& -relaxed_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - typedef typename add_pointer::type U_ptr; - U_ptr result = relaxed_get(boost::addressof(operand)); - - if (!result) - boost::throw_exception(bad_get()); - return static_cast(*result); -} - -#if defined(BOOST_MSVC) && (_MSC_VER < 1900) -# pragma warning(pop) -#endif - -#endif - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// strict_get(variant) methods -// -template -inline - typename add_pointer::type -strict_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::get(boost::variant*) will always return NULL" - ); - - return relaxed_get(operand); -} - -template -inline - typename add_pointer::type -strict_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element, const U >::value), - "boost::variant does not contain specified type U, " - "call to boost::get(const boost::variant*) will always return NULL" - ); - - return relaxed_get(operand); -} - -template -inline - typename add_reference::type -strict_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::get(boost::variant&) will always throw boost::bad_get exception" - ); - - return relaxed_get(operand); -} - -template -inline - typename add_reference::type -strict_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element, const U >::value), - "boost::variant does not contain specified type U, " - "call to boost::get(const boost::variant&) will always throw boost::bad_get exception" - ); - - return relaxed_get(operand); -} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -template -inline - U&& -strict_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - BOOST_STATIC_ASSERT_MSG( - (!boost::is_lvalue_reference::value), - "remove ampersand '&' from template type U in boost::get(boost::variant&&) " - ); - - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::get(const boost::variant&) will always throw boost::bad_get exception" - ); - - return relaxed_get(detail::variant::move(operand)); -} -#endif - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// get(variant) methods -// - -template -inline - typename add_pointer::type -get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return relaxed_get(operand); -#else - return strict_get(operand); -#endif - -} - -template -inline - typename add_pointer::type -get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return relaxed_get(operand); -#else - return strict_get(operand); -#endif -} - -template -inline - typename add_reference::type -get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return relaxed_get(operand); -#else - return strict_get(operand); -#endif -} - -template -inline - typename add_reference::type -get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return relaxed_get(operand); -#else - return strict_get(operand); -#endif -} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -template -inline - U&& -get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >&& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return relaxed_get(detail::variant::move(operand)); -#else - return strict_get(detail::variant::move(operand)); -#endif -} -#endif - -} // namespace boost - -#endif // BOOST_VARIANT_GET_HPP diff --git a/boost/variant/multivisitors.hpp b/boost/variant/multivisitors.hpp deleted file mode 100644 index c1ea3e0..0000000 --- a/boost/variant/multivisitors.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Boost.Varaint -// Multivisitors defined here -// -// See http://www.boost.org for most recent version, including documentation. -// -// Copyright (c) 2013-2023 Antony Polukhin. -// -// Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). - -#ifndef BOOST_VARIANT_MULTIVISITORS_HPP -#define BOOST_VARIANT_MULTIVISITORS_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include -#include // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE) -# include -# if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) -# include -# endif -#else -# include -#endif - -#endif // BOOST_VARIANT_MULTIVISITORS_HPP - diff --git a/boost/variant/polymorphic_get.hpp b/boost/variant/polymorphic_get.hpp deleted file mode 100644 index 55324ea..0000000 --- a/boost/variant/polymorphic_get.hpp +++ /dev/null @@ -1,352 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/polymorphic_get.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2013-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_POLYMORPHIC_GET_HPP -#define BOOST_VARIANT_POLYMORPHIC_GET_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// class bad_polymorphic_get -// -// The exception thrown in the event of a failed get of a value. -// -class BOOST_SYMBOL_VISIBLE bad_polymorphic_get - : public bad_get -{ -public: // std::exception implementation - - virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW - { - return "boost::bad_polymorphic_get: " - "failed value get using boost::polymorphic_get"; - } - -}; - -////////////////////////////////////////////////////////////////////////// -// function template get -// -// Retrieves content of given variant object if content is of type T. -// Otherwise: pointer ver. returns 0; reference ver. throws bad_get. -// - -namespace detail { namespace variant { - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// polymorphic metafunctions to detect index of a value -// - -template -struct element_polymorphic_iterator_impl : - boost::mpl::find_if< - Types, - boost::mpl::or_< - variant_element_functor, - variant_element_functor::type >, - boost::is_base_of - > - > -{}; - -template -struct holds_element_polymorphic : - boost::mpl::not_< - boost::is_same< - typename boost::mpl::end::type, - typename element_polymorphic_iterator_impl::type >::type - > - > -{}; - -// (detail) class template get_polymorphic_visitor -// -// Generic static visitor that: if the value is of the specified -// type or of a type derived from specified, returns a pointer -// to the value it visits; else a null pointer. -// -template -struct get_polymorphic_visitor -{ -private: // private typedefs - typedef get_polymorphic_visitor this_type; - typedef typename add_pointer::type pointer; - typedef typename add_reference::type reference; - - pointer get(reference operand, boost::true_type) const BOOST_NOEXCEPT - { - return boost::addressof(operand); - } - - template - pointer get(T&, boost::false_type) const BOOST_NOEXCEPT - { - return static_cast(0); - } - -public: // visitor interfaces - typedef pointer result_type; - - template - pointer operator()(U& operand) const BOOST_NOEXCEPT - { - typedef typename boost::remove_reference::type base_t; - typedef boost::integral_constant< - bool, - ( - boost::is_base_of::value && - (boost::is_const::value || !boost::is_const::value) - ) - || boost::is_same::value - || boost::is_same::type, U >::value - > tag_t; - - return this_type::get(operand, tag_t()); - } -}; - -}} // namespace detail::variant - -#ifndef BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE -# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) -# else -# if defined(BOOST_NO_CXX11_NULLPTR) -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ - , t* = 0 -# else -# define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t) \ - , t* = nullptr -# endif -# endif -#endif - -////////////////////////////////////////////////////////////////////////////////////////////////////////// -// polymorphic_relaxed_get -// - -template -inline - typename add_pointer::type -polymorphic_relaxed_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - typedef typename add_pointer::type U_ptr; - if (!operand) return static_cast(0); - - detail::variant::get_polymorphic_visitor v; - return operand->apply_visitor(v); -} - -template -inline - typename add_pointer::type -polymorphic_relaxed_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - typedef typename add_pointer::type U_ptr; - if (!operand) return static_cast(0); - - detail::variant::get_polymorphic_visitor v; - return operand->apply_visitor(v); -} - -template -inline - typename add_reference::type -polymorphic_relaxed_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - typedef typename add_pointer::type U_ptr; - U_ptr result = polymorphic_relaxed_get(&operand); - - if (!result) - boost::throw_exception(bad_polymorphic_get()); - return *result; -} - -template -inline - typename add_reference::type -polymorphic_relaxed_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - typedef typename add_pointer::type U_ptr; - U_ptr result = polymorphic_relaxed_get(&operand); - - if (!result) - boost::throw_exception(bad_polymorphic_get()); - return *result; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////// -// polymorphic_strict_get -// - -template -inline - typename add_pointer::type -polymorphic_strict_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element_polymorphic, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::polymorphic_get(boost::variant*) will always return NULL" - ); - - return polymorphic_relaxed_get(operand); -} - -template -inline - typename add_pointer::type -polymorphic_strict_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element_polymorphic, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::polymorphic_get(const boost::variant*) will always return NULL" - ); - - return polymorphic_relaxed_get(operand); -} - -template -inline - typename add_reference::type -polymorphic_strict_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element_polymorphic, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::polymorphic_get(boost::variant&) will always throw boost::bad_polymorphic_get exception" - ); - - return polymorphic_relaxed_get(operand); -} - -template -inline - typename add_reference::type -polymorphic_strict_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ - BOOST_STATIC_ASSERT_MSG( - (boost::detail::variant::holds_element_polymorphic, U >::value), - "boost::variant does not contain specified type U, " - "call to boost::polymorphic_get(const boost::variant&) will always throw boost::bad_polymorphic_get exception" - ); - - return polymorphic_relaxed_get(operand); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////// -// polymorphic_get(variant) methods -// - -template -inline - typename add_pointer::type -polymorphic_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return polymorphic_relaxed_get(operand); -#else - return polymorphic_strict_get(operand); -#endif - -} - -template -inline - typename add_pointer::type -polymorphic_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) BOOST_NOEXCEPT -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return polymorphic_relaxed_get(operand); -#else - return polymorphic_strict_get(operand); -#endif -} - -template -inline - typename add_reference::type -polymorphic_get( - boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return polymorphic_relaxed_get(operand); -#else - return polymorphic_strict_get(operand); -#endif -} - -template -inline - typename add_reference::type -polymorphic_get( - const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand - BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U) - ) -{ -#ifdef BOOST_VARIANT_USE_RELAXED_GET_BY_DEFAULT - return polymorphic_relaxed_get(operand); -#else - return polymorphic_strict_get(operand); -#endif -} -} // namespace boost - -#endif // BOOST_VARIANT_POLYMORPHIC_GET_HPP diff --git a/boost/variant/recursive_variant.hpp b/boost/variant/recursive_variant.hpp deleted file mode 100644 index 6248dc1..0000000 --- a/boost/variant/recursive_variant.hpp +++ /dev/null @@ -1,209 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/recursive_variant.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 Eric Friedman -// Copyright (c) 2013-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_RECURSIVE_VARIANT_HPP -#define BOOST_VARIANT_RECURSIVE_VARIANT_HPP - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace boost { - -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction specialization substitute -// -// Handles embedded variant types when substituting for recursive_variant_. -// - -#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -template < - BOOST_VARIANT_ENUM_PARAMS(typename T) - , typename RecursiveVariant - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) - > -struct substitute< - ::boost::variant< - recursive_flag< T0 > - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > - , RecursiveVariant - , ::boost::recursive_variant_ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) - > -{ - typedef ::boost::variant< - recursive_flag< T0 > - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > type; -}; - -template < - BOOST_VARIANT_ENUM_PARAMS(typename T) - , typename RecursiveVariant - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) - > -struct substitute< - ::boost::variant< - ::boost::detail::variant::over_sequence< T0 > - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > - , RecursiveVariant - , ::boost::recursive_variant_ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) - > -{ -private: - - typedef T0 initial_types; - - typedef typename mpl::transform< - initial_types - , mpl::protect< quoted_enable_recursive > - >::type types; - -public: - - typedef typename mpl::if_< - mpl::equal > - , ::boost::variant< - ::boost::detail::variant::over_sequence< T0 > - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > - , ::boost::variant< over_sequence > - >::type type; -}; - -template < - BOOST_VARIANT_ENUM_PARAMS(typename T) - , typename RecursiveVariant - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(typename Arity) - > -struct substitute< - ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) > - , RecursiveVariant - , ::boost::recursive_variant_ - BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(Arity) - > -{ -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - - typedef ::boost::variant< - typename enable_recursive< - T0 - , RecursiveVariant - , mpl::true_ - >::type, - typename enable_recursive< - TN - , RecursiveVariant - , mpl::true_ - >::type... - > type; - -#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -private: // helpers, for metafunction result (below) - - #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \ - typedef typename enable_recursive< \ - BOOST_PP_CAT(T,N) \ - , RecursiveVariant \ - , mpl::true_ \ - >::type BOOST_PP_CAT(wknd_T,N); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS - , _ - ) - - #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS - -public: // metafunction result - - typedef ::boost::variant< BOOST_VARIANT_ENUM_PARAMS(wknd_T) > type; -#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround -}; - -#else // defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -// -// no specializations: embedded variants unsupported on these compilers! -// - -#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) - -}} // namespace detail::variant - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_recursive_variant -// -// See docs and boost/variant/variant_fwd.hpp for more information. -// -template < BOOST_VARIANT_ENUM_PARAMS(typename T) > -struct make_recursive_variant -{ -public: // metafunction result - - typedef boost::variant< - detail::variant::recursive_flag< T0 > - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > type; - -}; - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_recursive_variant_over -// -// See docs and boost/variant/variant_fwd.hpp for more information. -// -template -struct make_recursive_variant_over -{ -private: // precondition assertions - - BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence::value )); - -public: // metafunction result - - typedef typename make_recursive_variant< - detail::variant::over_sequence< Types > - >::type type; - -}; - -} // namespace boost - -#endif // BOOST_VARIANT_RECURSIVE_VARIANT_HPP diff --git a/boost/variant/recursive_wrapper.hpp b/boost/variant/recursive_wrapper.hpp deleted file mode 100644 index f11418d..0000000 --- a/boost/variant/recursive_wrapper.hpp +++ /dev/null @@ -1,158 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/recursive_wrapper.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_HPP -#define BOOST_VARIANT_RECURSIVE_WRAPPER_HPP - -#include -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// class template recursive_wrapper -// -// See docs and recursive_wrapper_fwd.hpp for more information. -// - -template -class recursive_wrapper -{ -public: // typedefs - - typedef T type; - -private: // representation - - T* p_; - -public: // structors - - ~recursive_wrapper(); - recursive_wrapper(); - - recursive_wrapper(const recursive_wrapper& operand); - recursive_wrapper(const T& operand); - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - recursive_wrapper(recursive_wrapper&& operand); - recursive_wrapper(T&& operand); -#endif - -private: // helpers, for modifiers (below) - - void assign(const T& rhs); - -public: // modifiers - - recursive_wrapper& operator=(const recursive_wrapper& rhs) - { - assign( rhs.get() ); - return *this; - } - - recursive_wrapper& operator=(const T& rhs) - { - assign( rhs ); - return *this; - } - - void swap(recursive_wrapper& operand) BOOST_NOEXCEPT - { - T* temp = operand.p_; - operand.p_ = p_; - p_ = temp; - } - - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - recursive_wrapper& operator=(recursive_wrapper&& rhs) BOOST_NOEXCEPT - { - swap(rhs); - return *this; - } - - recursive_wrapper& operator=(T&& rhs) - { - get() = detail::variant::move(rhs); - return *this; - } -#endif - -public: // queries - - T& get() { return *get_pointer(); } - const T& get() const { return *get_pointer(); } - - T* get_pointer() { return p_; } - const T* get_pointer() const { return p_; } - -}; - -template -recursive_wrapper::~recursive_wrapper() -{ - boost::checked_delete(p_); -} - -template -recursive_wrapper::recursive_wrapper() - : p_(new T) -{ -} - -template -recursive_wrapper::recursive_wrapper(const recursive_wrapper& operand) - : p_(new T( operand.get() )) -{ -} - -template -recursive_wrapper::recursive_wrapper(const T& operand) - : p_(new T(operand)) -{ -} - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -template -recursive_wrapper::recursive_wrapper(recursive_wrapper&& operand) - : p_(new T( detail::variant::move(operand.get()) )) -{ -} - -template -recursive_wrapper::recursive_wrapper(T&& operand) - : p_(new T( detail::variant::move(operand) )) -{ -} -#endif - -template -void recursive_wrapper::assign(const T& rhs) -{ - this->get() = rhs; -} - -// function template swap -// -// Swaps two recursive_wrapper objects of the same type T. -// -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) BOOST_NOEXCEPT -{ - lhs.swap(rhs); -} - -} // namespace boost - -#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_HPP diff --git a/boost/variant/recursive_wrapper_fwd.hpp b/boost/variant/recursive_wrapper_fwd.hpp deleted file mode 100644 index b5d7e71..0000000 --- a/boost/variant/recursive_wrapper_fwd.hpp +++ /dev/null @@ -1,130 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/recursive_wrapper_fwd.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002 Eric Friedman, Itay Maman -// Copyright (c) 2016-2023 Antony Polukhin -// -// Portions Copyright (C) 2002 David Abrahams -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP -#define BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP - -#include -#include -#include -#include -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// class template recursive_wrapper -// -// Enables recursive types in templates by breaking cyclic dependencies. -// -// For example: -// -// class my; -// -// typedef variant< int, recursive_wrapper > var; -// -// class my { -// var var_; -// ... -// }; -// -template class recursive_wrapper; - - -/////////////////////////////////////////////////////////////////////////////// -// metafunction is_constructible partial specializations. -// -// recursive_wrapper is constructible only from T and recursive_wrapper. -// -template struct is_constructible, T> : boost::true_type{}; -template struct is_constructible, const T> : boost::true_type{}; -template struct is_constructible, T&> : boost::true_type{}; -template struct is_constructible, const T&> : boost::true_type{}; -template struct is_constructible, recursive_wrapper > : boost::true_type{}; -template struct is_constructible, const recursive_wrapper > : boost::true_type{}; -template struct is_constructible, recursive_wrapper& > : boost::true_type{}; -template struct is_constructible, const recursive_wrapper& > : boost::true_type{}; - -template struct is_constructible, U > : boost::false_type{}; -template struct is_constructible, const U > : boost::false_type{}; -template struct is_constructible, U& > : boost::false_type{}; -template struct is_constructible, const U& > : boost::false_type{}; -template struct is_constructible, recursive_wrapper > : boost::false_type{}; -template struct is_constructible, const recursive_wrapper > : boost::false_type{}; -template struct is_constructible, recursive_wrapper& > : boost::false_type{}; -template struct is_constructible, const recursive_wrapper& > : boost::false_type{}; - -// recursive_wrapper is not nothrow move constructible, because it's constructor does dynamic memory allocation. -// This specialisation is required to workaround GCC6 issue: https://svn.boost.org/trac/boost/ticket/12680 -template struct is_nothrow_move_constructible > : boost::false_type{}; - -/////////////////////////////////////////////////////////////////////////////// -// metafunction is_recursive_wrapper (modeled on code by David Abrahams) -// -// True if specified type matches recursive_wrapper. -// - -namespace detail { - - -template -struct is_recursive_wrapper_impl - : mpl::false_ -{ -}; - -template -struct is_recursive_wrapper_impl< recursive_wrapper > - : mpl::true_ -{ -}; - - -} // namespace detail - -template< typename T > struct is_recursive_wrapper - : public ::boost::integral_constant::value)> -{ -public: - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_recursive_wrapper,(T)) -}; - -/////////////////////////////////////////////////////////////////////////////// -// metafunction unwrap_recursive -// -// If specified type T matches recursive_wrapper, then U; else T. -// - - -template -struct unwrap_recursive -{ - typedef T type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,unwrap_recursive,(T)) -}; - -template -struct unwrap_recursive< recursive_wrapper > -{ - typedef T type; - - BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(1,unwrap_recursive,(T)) -}; - - -} // namespace boost - -#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP diff --git a/boost/variant/static_visitor.hpp b/boost/variant/static_visitor.hpp deleted file mode 100644 index ee40fec..0000000 --- a/boost/variant/static_visitor.hpp +++ /dev/null @@ -1,93 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/static_visitor.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_STATIC_VISITOR_HPP -#define BOOST_VARIANT_STATIC_VISITOR_HPP - -#include -#include - -#include -#include - -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// class template static_visitor -// -// An empty base class that typedefs the return type of a deriving static -// visitor. The class is analogous to std::unary_function in this role. -// - -namespace detail { - - struct is_static_visitor_tag { }; - - typedef void static_visitor_default_return; - -} // namespace detail - -template -class static_visitor - : public detail::is_static_visitor_tag -{ -public: // typedefs - - typedef R result_type; - -protected: // for use as base class only -#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS) - static_visitor() = default; -#else - static_visitor() BOOST_NOEXCEPT { } -#endif -}; - -////////////////////////////////////////////////////////////////////////// -// metafunction is_static_visitor -// -// Value metafunction indicates whether the specified type derives from -// static_visitor<...>. -// -// NOTE #1: This metafunction does NOT check whether the specified type -// fulfills the requirements of the StaticVisitor concept. -// -// NOTE #2: This template never needs to be specialized! -// - -namespace detail { - -template -struct is_static_visitor_impl -{ - BOOST_STATIC_CONSTANT(bool, value = - (::boost::is_base_and_derived< - detail::is_static_visitor_tag, - T - >::value)); -}; - -} // namespace detail - -template< typename T > struct is_static_visitor - : public ::boost::integral_constant::value)> -{ -public: - BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_static_visitor,(T)) -}; - -} // namespace boost - -#endif // BOOST_VARIANT_STATIC_VISITOR_HPP diff --git a/boost/variant/variant.hpp b/boost/variant/variant.hpp deleted file mode 100644 index 9a79264..0000000 --- a/boost/variant/variant.hpp +++ /dev/null @@ -1,2457 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/variant.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 Eric Friedman, Itay Maman -// Copyright (c) 2012-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Thanks to Adam Romanek for providing patches for exception-disabled env. - -#ifndef BOOST_VARIANT_VARIANT_HPP -#define BOOST_VARIANT_VARIANT_HPP - -#include // for std::size_t -#include // for placement new - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// Implementation Macros: -// -// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT -// Defined in boost/variant/detail/visitation_impl.hpp. -// -// BOOST_VARIANT_MINIMIZE_SIZE -// When #defined, implementation employs all known means to minimize the -// size of variant obje cts. However, often unsuccessful due to alignment -// issues, and potentially harmful to runtime speed, so not enabled by -// default. (TODO: Investigate further.) - -#if defined(BOOST_VARIANT_MINIMIZE_SIZE) -# include // for SCHAR_MAX -# include -# include -# include -# include -# include -# include -# include -# include -#endif - - -namespace boost { - -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction max_value -// -// Finds the maximum value of the unary metafunction F over Sequence. -// -template -struct max_value -{ -private: // helpers, for metafunction result (below) - - typedef typename mpl::transform1::type transformed_; - typedef typename mpl::max_element::type max_it; - -public: // metafunction result - - typedef typename mpl::deref::type - type; - -}; - -struct add_alignment -{ - template - struct apply - : mpl::size_t< - ::boost::integer::static_lcm< - BOOST_MPL_AUX_VALUE_WKND(State)::value - , ::boost::alignment_of::value - >::value - > - {}; -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction find_fallback_type -// -// Provides a fallback (i.e., nothrow default-constructible) type from the -// specified sequence, or no_fallback_type if not found. -// -// This implementation is designed to prefer boost::blank over other potential -// fallback types, regardless of its position in the specified sequence. -// - -class no_fallback_type; - -struct find_fallback_type_pred -{ - template - struct apply - { - private: - typedef typename mpl::deref::type t_; - - public: - typedef mpl::not_< has_nothrow_constructor > type; - }; -}; - -template -struct find_fallback_type -{ -private: // helpers, for metafunction result (below) - - typedef typename mpl::end::type end_it; - - // [Find the first suitable fallback type...] - - typedef typename mpl::iter_fold_if< - Types - , mpl::int_<0>, mpl::protect< mpl::next<> > - , mpl::protect< find_fallback_type_pred > - >::type first_result_; - - typedef typename first_result_::first first_result_index; - typedef typename first_result_::second first_result_it; - - // [...now search the rest of the sequence for boost::blank...] - - typedef typename mpl::iter_fold_if< - mpl::iterator_range< first_result_it,end_it > - , first_result_index, mpl::protect< mpl::next<> > - , mpl::protect< mpl::not_same_as > - >::type second_result_; - - typedef typename second_result_::second second_result_it; - -public: // metafunction result - - // [...and return the results of the search:] - typedef typename mpl::eval_if< - is_same< second_result_it,end_it > - , mpl::if_< - is_same< first_result_it,end_it > - , mpl::pair< no_fallback_type,no_fallback_type > - , first_result_ - > - , mpl::identity< second_result_ > - >::type type; - -}; - -#ifndef BOOST_NO_CXX11_NOEXCEPT -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_variant_move_noexcept_constructible -// -// Returns true_type if all the types are nothrow move constructible. -// -template -struct is_variant_move_noexcept_constructible { - typedef typename boost::mpl::find_if< - Types, mpl::not_ > - >::type iterator_t; - - typedef typename boost::mpl::end::type end_t; - typedef typename boost::is_same< - iterator_t, end_t - >::type type; -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_variant_move_noexcept_assignable -// -// Returns true_type if all the types are nothrow move constructible. -// -template -struct is_variant_move_noexcept_assignable { - typedef typename boost::mpl::find_if< - Types, mpl::not_ > - >::type iterator_t; - - typedef typename boost::mpl::end::type end_t; - typedef typename boost::is_same< - iterator_t, end_t - >::type type; -}; -#endif // BOOST_NO_CXX11_NOEXCEPT - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction is_variant_constructible_from -// -// Derives from true_type if at least one variant's type is constructible from T. -// -template -struct is_constructible_ext: - boost::mpl::or_< - boost::is_constructible< - T1, - T2 - >, - boost::is_constructible< - T1, - typename boost::add_lvalue_reference::type - > - > -{}; - -template -struct is_variant_constructible_from: - boost::mpl::not_< boost::is_same< - typename boost::mpl::find_if< - Types, - is_constructible_ext - >::type, - typename boost::mpl::end::type - > > -{}; - -template -struct is_variant_constructible_from< boost::variant, Types >: - boost::is_same< - typename boost::mpl::find_if< - typename boost::variant::recursive_enabled_types, - mpl::not_< is_variant_constructible_from< boost::mpl::_1, Types> > - >::type, - typename boost::mpl::end< typename boost::variant::recursive_enabled_types >::type - > -{}; - -template -struct is_variant_constructible_from< const boost::variant& , Types >: - is_variant_constructible_from, Types > -{}; - -template -struct is_variant_constructible_from< boost::variant& , Types >: - is_variant_constructible_from, Types > -{}; - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -template -struct is_variant_constructible_from< boost::variant&& , Types >: - is_variant_constructible_from, Types > -{}; - -template -struct is_variant_constructible_from< boost::variant const && , Types >: - is_variant_constructible_from, Types > -{}; - -#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCE - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) metafunction make_storage -// -// Provides an aligned storage type capable of holding any of the types -// specified in the given type-sequence. -// - -template -struct make_storage -{ -private: // helpers, for metafunction result (below) - - typedef typename mpl::eval_if< - NeverUsesBackupFlag - , mpl::identity< Types > - , mpl::push_front< - Types, backup_holder - > - >::type types; - - typedef typename max_value< - types, mpl::sizeof_ - >::type max_size; - -#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) - - typedef typename mpl::fold< - types - , mpl::size_t<1> - , add_alignment - >::type max_alignment; - -#else // borland - - // temporary workaround -- use maximal alignment - typedef mpl::size_t< -1 > max_alignment; - -#endif // borland workaround - -public: // metafunction result - - typedef ::boost::aligned_storage< - BOOST_MPL_AUX_VALUE_WKND(max_size)::value - , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value - > type; -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class destroyer -// -// Internal visitor that destroys the value it visits. -// -struct destroyer - : public static_visitor<> -{ -public: // visitor interfaces - - template - void internal_visit(T& operand, int) const BOOST_NOEXCEPT - { - operand.~T(); // must be noexcept - -#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0551)) || \ - BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) - (void)operand; // suppresses warnings -#endif - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class template known_get -// -// Visitor that returns a reference to content of the specified type. -// -// Precondition: visited variant MUST contain logical content of type T. -// -template -class known_get - : public static_visitor -{ - -public: // visitor interface - - T& operator()(T& operand) const BOOST_NOEXCEPT - { - return operand; - } - - template - T& operator()(U&) const - { - // logical error to be here: see precondition above - return ::boost::detail::variant::forced_return< T& >(); - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class copy_into -// -// Internal visitor that copies the value it visits into the given buffer. -// -class copy_into - : public static_visitor<> -{ -private: // representation - - void* storage_; - -public: // structors - - explicit copy_into(void* storage) BOOST_NOEXCEPT - : storage_(storage) - { - } - -public: // internal visitor interface - - template - void internal_visit(boost::detail::variant::backup_holder& operand, long) const - { - new(storage_) T( operand.get() ); - } - - template - void internal_visit(const boost::detail::variant::backup_holder& operand, long) const - { - new(storage_) T( operand.get() ); - } - - template - void internal_visit(const T& operand, int) const - { - new(storage_) T(operand); - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class move_into -// -// Internal visitor that moves the value it visits into the given buffer. -// -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES -class move_into - : public static_visitor<> -{ -private: // representation - - void* storage_; - -public: // structors - - explicit move_into(void* storage) BOOST_NOEXCEPT - : storage_(storage) - { - } - -public: // internal visitor interface - - template - void internal_visit(boost::detail::variant::backup_holder& operand, long) const - { - new(storage_) T( ::boost::detail::variant::move(operand.get()) ); - } - - template - void internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval()))) - { - new(storage_) T(::boost::detail::variant::move(operand)); - } -}; -#endif - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class assign_storage -// -// Internal visitor that assigns the given storage (which must be a -// constructed value of the same type) to the value it visits. -// -struct assign_storage - : public static_visitor<> -{ -private: // representation - - const void* rhs_storage_; - -public: // structors - - explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT - : rhs_storage_(rhs_storage) - { - } - -public: // internal visitor interfaces - - template - void internal_visit(backup_holder& lhs_content, long) const - { - lhs_content.get() - = static_cast< const backup_holder* >(rhs_storage_)->get(); - } - - template - void internal_visit(const backup_holder& lhs_content, long) const - { - lhs_content.get() - = static_cast< const backup_holder* >(rhs_storage_)->get(); - } - - template - void internal_visit(T& lhs_content, int) const - { - // NOTE TO USER : - // Compile error here indicates one of variant's bounded types does - // not meet the requirements of the Assignable concept. Thus, - // variant is not Assignable. - // - // Hint: Are any of the bounded types const-qualified or references? - // - lhs_content = *static_cast< const T* >(rhs_storage_); - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class move_storage -// -// Internal visitor that moves the given storage (which must be a -// constructed value of the same type) to the value it visits. -// -struct move_storage - : public static_visitor<> -{ -private: // representation - - void* rhs_storage_; - -public: // structors - - explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT - : rhs_storage_(rhs_storage) - { - } - -public: // internal visitor interfaces - - template - void internal_visit(backup_holder& lhs_content, long) const - { - lhs_content.get() - = ::boost::detail::variant::move(static_cast* >(rhs_storage_)->get()); - } - - template - void internal_visit(const backup_holder& lhs_content, long) const - { - lhs_content.get() - = ::boost::detail::variant::move(static_cast* >(rhs_storage_)->get()); - } - - template - void internal_visit(T& lhs_content, int) const - { - // NOTE TO USER : - // Compile error here indicates one of variant's bounded types does - // not meet the requirements of the Assignable concept. Thus, - // variant is not Assignable. - // - // Hint: Are any of the bounded types const-qualified or references? - // - lhs_content = ::boost::detail::variant::move(*static_cast(rhs_storage_)); - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class direct_assigner -// -// Generic static visitor that: if and only if the visited value is of the -// specified type, assigns the given value to the visited value and returns -// true; else returns false. -// -template -class direct_assigner - : public static_visitor -{ -private: // representation - - const T& rhs_; - -public: // structors - - explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT - : rhs_(rhs) - { - } - -public: // visitor interface - - bool operator()(T& lhs) - { - lhs = rhs_; - return true; - } - - template - bool operator()(U&) BOOST_NOEXCEPT - { - return false; - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) -private: - // silence MSVC warning C4512: assignment operator could not be generated - direct_assigner& operator= (direct_assigner const&); -#endif -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class direct_mover -// -// Generic static visitor that: if and only if the visited value is of the -// specified type, move assigns the given value to the visited value and returns -// true; else returns false. -// -template -class direct_mover - : public static_visitor -{ -private: // representation - - T& rhs_; - -public: // structors - - explicit direct_mover(T& rhs) BOOST_NOEXCEPT - : rhs_(rhs) - { - } - -public: // visitor interface - - bool operator()(T& lhs) - { - lhs = ::boost::detail::variant::move(rhs_); - return true; - } - - template - bool operator()(U&) BOOST_NOEXCEPT - { - return false; - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) -private: - // silence MSVC warning C4512: assignment operator could not be generated - direct_mover& operator= (direct_mover const&); -#endif -}; - - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class backup_assigner -// -// Internal visitor that "assigns" the given value to the visited value, -// using backup to recover if the destroy-copy sequence fails. -// -// NOTE: This needs to be a friend of variant, as it needs access to -// indicate_which, indicate_backup_which, etc. -// -template -class backup_assigner - : public static_visitor<> -{ -private: // representation - - Variant& lhs_; - int rhs_which_; - const void* rhs_content_; - void (*copy_rhs_content_)(void*, const void*); - -public: // structors - - template - backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content) - : lhs_(lhs) - , rhs_which_(rhs_which) - , rhs_content_(&rhs_content) - , copy_rhs_content_(&construct_impl) - { - } - -private: // helpers, for visitor interface (below) - - template - static void construct_impl(void* addr, const void* obj) - { - new(addr) RhsT(*static_cast(obj)); - } - - template - void backup_assign_impl( - backup_holder& lhs_content - , mpl::false_ // is_nothrow_move_constructible - , long - ) - { - // Move lhs content to backup... - backup_holder backup_lhs_content(0); - backup_lhs_content.swap(lhs_content); // nothrow - - // ...destroy lhs content... - lhs_content.~backup_holder(); // nothrow - - BOOST_TRY - { - // ...and attempt to copy rhs content into lhs storage: - copy_rhs_content_(lhs_.storage_.address(), rhs_content_); - } - BOOST_CATCH (...) - { - // In case of failure, copy backup pointer to lhs storage... - new(lhs_.storage_.address()) - backup_holder( 0 ); // nothrow - - static_cast* >(lhs_.storage_.address()) - ->swap(backup_lhs_content); // nothrow - - // ...and rethrow: - BOOST_RETHROW; - } - BOOST_CATCH_END - - // In case of success, indicate new content type: - lhs_.indicate_which(rhs_which_); // nothrow - } - - template - void backup_assign_impl( - LhsT& lhs_content - , mpl::true_ // is_nothrow_move_constructible - , int - ) - { - // Move lhs content to backup... - LhsT backup_lhs_content( - ::boost::detail::variant::move(lhs_content) - ); // nothrow - - // ...destroy lhs content... - lhs_content.~LhsT(); // nothrow - - BOOST_TRY - { - // ...and attempt to copy rhs content into lhs storage: - copy_rhs_content_(lhs_.storage_.address(), rhs_content_); - } - BOOST_CATCH (...) - { - // In case of failure, restore backup content to lhs storage... - new(lhs_.storage_.address()) - LhsT( - ::boost::detail::variant::move(backup_lhs_content) - ); // nothrow - - // ...and rethrow: - BOOST_RETHROW; - } - BOOST_CATCH_END - - // In case of success, indicate new content type: - lhs_.indicate_which(rhs_which_); // nothrow - } - - template - void backup_assign_impl( - LhsT& lhs_content - , mpl::false_ // is_nothrow_move_constructible - , int - ) - { - // Backup lhs content... - LhsT* backup_lhs_ptr = new LhsT(lhs_content); - - // ...destroy lhs content... - lhs_content.~LhsT(); // nothrow - - BOOST_TRY - { - // ...and attempt to copy rhs content into lhs storage: - copy_rhs_content_(lhs_.storage_.address(), rhs_content_); - } - BOOST_CATCH (...) - { - // In case of failure, copy backup pointer to lhs storage... - new(lhs_.storage_.address()) - backup_holder( backup_lhs_ptr ); // nothrow - - // ...indicate now using backup... - lhs_.indicate_backup_which( lhs_.which() ); // nothrow - - // ...and rethrow: - BOOST_RETHROW; - } - BOOST_CATCH_END - - // In case of success, indicate new content type... - lhs_.indicate_which(rhs_which_); // nothrow - - // ...and delete backup: - delete backup_lhs_ptr; // nothrow - } - -public: // visitor interface - - template - void internal_visit(LhsT& lhs_content, int) - { - typedef typename is_nothrow_move_constructible::type - nothrow_move; - - backup_assign_impl( lhs_content, nothrow_move(), 1L); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) -private: - // silence MSVC warning C4512: assignment operator could not be generated - backup_assigner& operator= (backup_assigner const&); -#endif -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class swap_with -// -// Visitor that swaps visited value with content of given variant. -// -// Precondition: Given variant MUST have same logical type as visited value. -// -template -struct swap_with - : public static_visitor<> -{ -private: // representation - - Variant& toswap_; - -public: // structors - - explicit swap_with(Variant& toswap) BOOST_NOEXCEPT - : toswap_(toswap) - { - } - -public: // internal visitor interfaces - - template - void operator()(T& operand) const - { - // Since the precondition ensures types are same, get T... - known_get getter; - T& other = toswap_.apply_visitor(getter); - - // ...and swap: - ::boost::detail::variant::move_swap( operand, other ); - } - -private: - swap_with& operator=(const swap_with&); - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class reflect -// -// Generic static visitor that performs a typeid on the value it visits. -// - -class reflect - : public static_visitor -{ -public: // visitor interfaces - - template - const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT - { - return boost::typeindex::type_id().type_info(); - } - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class comparer -// -// Generic static visitor that compares the content of the given lhs variant -// with the visited rhs content using Comp. -// -// Precondition: lhs.which() == rhs.which() -// -template -class comparer - : public static_visitor -{ -private: // representation - - const Variant& lhs_; - -public: // structors - - explicit comparer(const Variant& lhs) BOOST_NOEXCEPT - : lhs_(lhs) - { - } - -public: // visitor interfaces - - template - bool operator()(T& rhs_content) const - { - // Since the precondition ensures lhs and rhs types are same, get T... - known_get getter; - const T& lhs_content = lhs_.apply_visitor(getter); - - // ...and compare lhs and rhs contents: - return Comp()(lhs_content, rhs_content); - } - -private: - comparer& operator=(const comparer&); - -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class equal_comp -// -// Generic function object compares lhs with rhs using operator==. -// -struct equal_comp -{ - template - bool operator()(const T& lhs, const T& rhs) const - { - return lhs == rhs; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class less_comp -// -// Generic function object compares lhs with rhs using operator<. -// -struct less_comp -{ - template - bool operator()(const T& lhs, const T& rhs) const - { - return lhs < rhs; - } -}; - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class template invoke_visitor -// -// Internal visitor that invokes the given visitor using: -// * for wrappers (e.g., recursive_wrapper), the wrapper's held value. -// * for all other values, the value itself. -// -template -class invoke_visitor -{ -private: // representation - - Visitor& visitor_; - -public: // visitor typedefs - - typedef typename Visitor::result_type - result_type; - -public: // structors - - explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT - : visitor_(visitor) - { - } - -public: // internal visitor interfaces - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - - //using workaround with is_same to prenvent compilation error, because we need to use T in enable_if to make SFINAE work - template - typename enable_if_c::value, result_type>::type internal_visit(T&& operand, int) - { - return visitor_(::boost::move(operand)); - } - - //using workaround with is_same to prenvent compilation error, because we need to use T in enable_if to make SFINAE work - template - typename disable_if_c::value, result_type>::type internal_visit(T&& operand, int) - { - return visitor_(operand); - } - -#else - - template - result_type internal_visit(T& operand, int) - { - return visitor_(operand); - } - -# if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564)) - template - result_type internal_visit(const T& operand, int) - { - return visitor_(operand); - } -# endif //BORLAND - -#endif //RVALUE REFERENCES - -public: // internal visitor interfaces, cont. - - template - result_type internal_visit(boost::recursive_wrapper& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - - template - result_type internal_visit(const boost::recursive_wrapper& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - - template - result_type internal_visit(boost::detail::reference_content& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - - template - result_type internal_visit(const boost::detail::reference_content& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - - template - result_type internal_visit(boost::detail::variant::backup_holder& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - - template - result_type internal_visit(const boost::detail::variant::backup_holder& operand, long) - { - return internal_visit( operand.get(), 1L ); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) -private: - // silence MSVC warning C4512: assignment operator could not be generated - invoke_visitor& operator= (invoke_visitor const&); -#endif -}; - -}} // namespace detail::variant - -/////////////////////////////////////////////////////////////////////////////// -// class template variant (concept inspired by Andrei Alexandrescu) -// -// See docs and boost/variant/variant_fwd.hpp for more information. -// -template < - typename T0_ - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T) - > -class variant -{ -private: // helpers, for typedefs (below) - - typedef variant wknd_self_t; - - struct is_recursive_ - : detail::variant::is_recursive_flag - { - }; - - typedef typename mpl::eval_if< - is_recursive_ - , T0_ - , mpl::identity< T0_ > - >::type unwrapped_T0_; - - struct is_sequence_based_ - : detail::variant::is_over_sequence - { - }; - -#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) - -private: // helpers, for typedefs (below) - - typedef typename mpl::eval_if< - is_sequence_based_ - , unwrapped_T0_ // over_sequence<...>::type - , detail::variant::make_variant_list< - unwrapped_T0_ - , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T) - > - >::type specified_types; - - BOOST_STATIC_ASSERT(( - ::boost::mpl::not_< mpl::empty >::value - )); - -public: // public typedefs - typedef typename mpl::eval_if< - is_recursive_ - , mpl::transform< - specified_types - , mpl::protect< - detail::variant::quoted_enable_recursive - > - > - , mpl::identity< specified_types > - >::type recursive_enabled_types; // used by is_variant_constructible_from<> trait - - typedef typename mpl::transform< - recursive_enabled_types - , unwrap_recursive - >::type types; - -private: // internal typedefs - - typedef typename mpl::transform< - recursive_enabled_types - , mpl::protect< detail::make_reference_content<> > - >::type internal_types; - - typedef typename mpl::front< - internal_types - >::type internal_T0; - -#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) - -private: // helpers, for typedefs (below) - - typedef unwrapped_T0_ T0; - - #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \ - typedef typename mpl::eval_if< \ - is_recursive_ \ - , detail::variant::enable_recursive< \ - BOOST_PP_CAT(T,N) \ - , wknd_self_t \ - > \ - , mpl::identity< BOOST_PP_CAT(T,N) > \ - >::type BOOST_PP_CAT(recursive_enabled_T,N); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS - , _ - ) - - #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS - - #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \ - typedef typename unwrap_recursive< \ - BOOST_PP_CAT(recursive_enabled_T,N) \ - >::type BOOST_PP_CAT(public_T,N); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS - , _ - ) - - #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS - -public: // public typedefs - - typedef typename detail::variant::make_variant_list< - BOOST_VARIANT_ENUM_PARAMS(public_T) - >::type types; - -private: // helpers, for internal typedefs (below) - - #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \ - typedef detail::make_reference_content< \ - BOOST_PP_CAT(recursive_enabled_T,N) \ - >::type BOOST_PP_CAT(internal_T,N); \ - /**/ - - BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS - , _ - ) - - #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS - -private: // internal typedefs - - typedef typename detail::variant::make_variant_list< - BOOST_VARIANT_ENUM_PARAMS(internal_T) - >::type internal_types; - -private: // static precondition assertions - - // NOTE TO USER : - // variant< type-sequence > syntax is not supported on this compiler! - // - BOOST_MPL_ASSERT_NOT(( is_sequence_based_ )); - -#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround - -private: // helpers, for representation (below) - - typedef typename detail::variant::find_fallback_type< - internal_types - >::type fallback_type_result_; - - typedef typename fallback_type_result_::first - fallback_type_index_; - typedef typename fallback_type_result_::second - fallback_type_; - - struct has_fallback_type_ - : mpl::not_< - is_same< fallback_type_, detail::variant::no_fallback_type > - > - { - }; - - typedef has_fallback_type_ - never_uses_backup_flag; - - typedef typename detail::variant::make_storage< - internal_types, never_uses_backup_flag - >::type storage_t; - -#ifndef BOOST_NO_CXX11_NOEXCEPT - typedef typename detail::variant::is_variant_move_noexcept_constructible< - internal_types - > variant_move_noexcept_constructible; - - typedef typename detail::variant::is_variant_move_noexcept_assignable< - internal_types - > variant_move_noexcept_assignable; - -#endif - -private: // helpers, for representation (below) - - // which_ on: - // * [0, size) indicates stack content - // * [-size, 0) indicates pointer to heap backup - // if which_ >= 0: - // * then which() -> which_ - // * else which() -> -(which_ + 1) - -#if !defined(BOOST_VARIANT_MINIMIZE_SIZE) - - typedef int which_t; - -#else // defined(BOOST_VARIANT_MINIMIZE_SIZE) - - // [if O1_size available, then attempt which_t size optimization...] - // [select signed char if fewer than SCHAR_MAX types, else signed int:] - typedef typename mpl::eval_if< - mpl::equal_to< mpl::O1_size, mpl::long_<-1> > - , mpl::identity< int > - , mpl::if_< - mpl::less< mpl::O1_size, mpl::int_ > - , signed char - , int - > - >::type which_t; - -#endif // BOOST_VARIANT_MINIMIZE_SIZE switch - -// representation -- private when possible -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - private: -#else - public: -#endif - - which_t which_; - storage_t storage_; - - void indicate_which(int which_arg) BOOST_NOEXCEPT - { - which_ = static_cast( which_arg ); - } - - void indicate_backup_which(int which_arg) BOOST_NOEXCEPT - { - which_ = static_cast( -(which_arg + 1) ); - } - -private: // helpers, for queries (below) - - bool using_backup() const BOOST_NOEXCEPT - { - return which_ < 0; - } - -public: // queries - - int which() const BOOST_NOEXCEPT - { - // If using heap backup... - if (using_backup()) - // ...then return adjusted which_: - return -(which_ + 1); - - // Otherwise, return which_ directly: - return which_; - } - -private: // helpers, for structors (below) - - struct initializer - : BOOST_VARIANT_AUX_INITIALIZER_T( - recursive_enabled_types, recursive_enabled_T - ) - { - }; - - void destroy_content() BOOST_NOEXCEPT - { - detail::variant::destroyer visitor; - this->internal_apply_visitor(visitor); - } - -public: // structors - - ~variant() BOOST_NOEXCEPT - { - destroy_content(); - } - - variant() -#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130)) - BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor::value) -#endif - { -#ifdef _MSC_VER -#pragma warning( push ) -// behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized -#pragma warning( disable : 4345 ) -#endif - // NOTE TO USER : - // Compile error from here indicates that the first bound - // type is not default-constructible, and so variant cannot - // support its own default-construction. - // - new( storage_.address() ) internal_T0(); - indicate_which(0); // zero is the index of the first bounded type -#ifdef _MSC_VER -#pragma warning( pop ) -#endif - } - -private: // helpers, for structors, cont. (below) - - class convert_copy_into - : public static_visitor - { - private: // representation - - void* storage_; - - public: // structors - - explicit convert_copy_into(void* storage) BOOST_NOEXCEPT - : storage_(storage) - { - } - - public: // internal visitor interfaces (below) - - template - int internal_visit(T& operand, int) const - { - // NOTE TO USER : - // Compile error here indicates one of the source variant's types - // cannot be unambiguously converted to the destination variant's - // types (or that no conversion exists). - // - return initializer::initialize(storage_, operand); - } - -# if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564)) - template - result_type internal_visit(const T& operand, int) const - { - return initializer::initialize(storage_, operand); - } -# endif - - template - int internal_visit(boost::detail::reference_content& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::detail::reference_content& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(boost::detail::variant::backup_holder& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::detail::variant::backup_holder& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(boost::recursive_wrapper& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::recursive_wrapper& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - }; - - friend class convert_copy_into; - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - class convert_move_into - : public static_visitor - { - private: // representation - - void* storage_; - - public: // structors - - explicit convert_move_into(void* storage) BOOST_NOEXCEPT - : storage_(storage) - { - } - - public: // internal visitor interfaces (below) - - template - int internal_visit(T& operand, int) const - { - // NOTE TO USER : - // Compile error here indicates one of the source variant's types - // cannot be unambiguously converted to the destination variant's - // types (or that no conversion exists). - // - return initializer::initialize(storage_, detail::variant::move(operand) ); - } - - template - int internal_visit(boost::detail::reference_content& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::detail::reference_content& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(boost::detail::variant::backup_holder& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::detail::variant::backup_holder& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(boost::recursive_wrapper& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - - template - int internal_visit(const boost::recursive_wrapper& operand, long) const - { - return internal_visit( operand.get(), 1L ); - } - }; - - friend class convert_move_into; -#endif - -private: // helpers, for structors, below - - template - void convert_construct( - T& operand - , int - , mpl::false_ = mpl::false_() // is_foreign_variant - ) - { - // NOTE TO USER : - // Compile error here indicates that the given type is not - // unambiguously convertible to one of the variant's types - // (or that no conversion exists). - // - indicate_which( - initializer::initialize( - storage_.address() - , operand - ) - ); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - typename boost::enable_if >::type convert_construct( - T&& operand - , int - , mpl::false_ = mpl::false_() // is_foreign_variant - ) - { - // NOTE TO USER : - // Compile error here indicates that the given type is not - // unambiguously convertible to one of the variant's types - // (or that no conversion exists). - // - indicate_which( - initializer::initialize( - storage_.address() - , detail::variant::move(operand) - ) - ); - } -#endif - - template - void convert_construct( - Variant& operand - , long - , mpl::true_// is_foreign_variant - ) - { - convert_copy_into visitor(storage_.address()); - indicate_which( - operand.internal_apply_visitor(visitor) - ); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - typename boost::enable_if >::type convert_construct( - Variant&& operand - , long - , mpl::true_// is_foreign_variant - ) - { - convert_move_into visitor(storage_.address()); - indicate_which( - operand.internal_apply_visitor(visitor) - ); - } -#endif - - template - void convert_construct_variant(Variant& operand) - { - // [Determine if the given variant is itself a bounded type, or if its - // content needs to be converted (i.e., it is a 'foreign' variant):] - // - - typedef typename mpl::find_if< - types - , is_same< - add_const - , const Variant - > - >::type found_it; - - typedef typename mpl::end::type not_found; - typedef typename is_same< - found_it, not_found - >::type is_foreign_variant; - - // Convert construct from operand: - convert_construct( - operand, 1L - , is_foreign_variant() - ); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - typename boost::enable_if >::type convert_construct_variant(Variant&& operand) - { - // [Determine if the given variant is itself a bounded type, or if its - // content needs to be converted (i.e., it is a 'foreign' variant):] - // - - typedef typename mpl::find_if< - types - , is_same< - add_const - , const Variant - > - >::type found_it; - - typedef typename mpl::end::type not_found; - typedef typename is_same< - found_it, not_found - >::type is_foreign_variant; - - // Convert move construct from operand: - convert_construct( - detail::variant::move(operand), 1L - , is_foreign_variant() - ); - } -#endif - - template - typename boost::enable_if, variant>, - boost::detail::variant::is_variant_constructible_from&, internal_types> - > >::type convert_construct( - boost::variant& operand - , long - ) - { - convert_construct_variant(operand); - } - - template - typename boost::enable_if, variant>, - boost::detail::variant::is_variant_constructible_from&, internal_types> - > >::type convert_construct( - const boost::variant& operand - , long - ) - { - convert_construct_variant(operand); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - typename boost::enable_if, variant>, - boost::detail::variant::is_variant_constructible_from&&, internal_types> - > >::type convert_construct( - boost::variant&& operand - , long - ) - { - convert_construct_variant( detail::variant::move(operand) ); - } -#endif - -public: // structors, cont. - - template - variant(const T& operand, - typename boost::enable_if >, - boost::detail::variant::is_variant_constructible_from - >, - boost::is_same >, - bool >::type = true) - { - convert_construct(operand, 1L); - } - - template - variant( - T& operand - , typename boost::enable_if >, - mpl::not_< boost::is_same >, - boost::detail::variant::is_variant_constructible_from - >, - boost::is_same >, - bool >::type = true - ) - { - convert_construct(operand, 1L); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - variant(T&& operand, - typename boost::enable_if, - mpl::not_< boost::is_const >, - mpl::not_< boost::is_same >, - boost::detail::variant::is_variant_constructible_from - >, - boost::is_same >, - bool >::type = true) - { - convert_construct( detail::variant::move(operand), 1L); - } -#endif - -public: // structors, cont. - - // [MSVC6 requires copy constructor appear after template constructors] - variant(const variant& operand) - { - // Copy the value of operand into *this... - detail::variant::copy_into visitor( storage_.address() ); - operand.internal_apply_visitor(visitor); - - // ...and activate the *this's primary storage on success: - indicate_which(operand.which()); - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value) - { - // Move the value of operand into *this... - detail::variant::move_into visitor( storage_.address() ); - operand.internal_apply_visitor(visitor); - - // ...and activate the *this's primary storage on success: - indicate_which(operand.which()); - } -#endif - -private: // helpers, for modifiers (below) - -# if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend class detail::variant::backup_assigner; -# endif - - // class assigner - // - // Internal visitor that "assigns" the visited value to the given variant - // by appropriate destruction and copy-construction. - // - - class assigner - : public static_visitor<> - { - protected: // representation - - variant& lhs_; - const int rhs_which_; - - public: // structors - - assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT - : lhs_(lhs) - , rhs_which_(rhs_which) - { - } - - protected: // helpers, for internal visitor interface (below) - - template - void assign_impl( - const RhsT& rhs_content - , mpl::true_ // has_nothrow_copy - , B1 // is_nothrow_move_constructible - , B2 // has_fallback_type - ) const BOOST_NOEXCEPT - { - // Destroy lhs's content... - lhs_.destroy_content(); // nothrow - - // ...copy rhs content into lhs's storage... - new(lhs_.storage_.address()) - RhsT( rhs_content ); // nothrow - - // ...and indicate new content type: - lhs_.indicate_which(rhs_which_); // nothrow - } - - template - void assign_impl( - const RhsT& rhs_content - , mpl::false_ // has_nothrow_copy - , mpl::true_ // is_nothrow_move_constructible - , B // has_fallback_type - ) const - { - // Attempt to make a temporary copy (so as to move it below)... - RhsT temp(rhs_content); - - // ...and upon success destroy lhs's content... - lhs_.destroy_content(); // nothrow - - // ...move the temporary copy into lhs's storage... - new(lhs_.storage_.address()) - RhsT( detail::variant::move(temp) ); // nothrow - - // ...and indicate new content type: - lhs_.indicate_which(rhs_which_); // nothrow - } - - void construct_fallback() const BOOST_NOEXCEPT { - // In case of failure, default-construct fallback type in lhs's storage... - new (lhs_.storage_.address()) - fallback_type_; // nothrow - - // ...indicate construction of fallback type... - lhs_.indicate_which( - BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value - ); // nothrow - } - - template - void assign_impl( - const RhsT& rhs_content - , mpl::false_ // has_nothrow_copy - , mpl::false_ // is_nothrow_move_constructible - , mpl::true_ // has_fallback_type - ) const - { - // Destroy lhs's content... - lhs_.destroy_content(); // nothrow - - BOOST_TRY - { - // ...and attempt to copy rhs's content into lhs's storage: - new(lhs_.storage_.address()) - RhsT( rhs_content ); - } - BOOST_CATCH (...) - { - construct_fallback(); - - // ...and rethrow: - BOOST_RETHROW; - } - BOOST_CATCH_END - - // In the event of success, indicate new content type: - lhs_.indicate_which(rhs_which_); // nothrow - } - - template - void assign_impl( - const RhsT& rhs_content - , mpl::false_ // has_nothrow_copy - , mpl::false_ // is_nothrow_move_constructible - , mpl::false_ // has_fallback_type - ) const - { - detail::variant::backup_assigner - visitor(lhs_, rhs_which_, rhs_content); - lhs_.internal_apply_visitor(visitor); - } - - public: // internal visitor interfaces - - template - void internal_visit(const RhsT& rhs_content, int) const - { - typedef typename has_nothrow_copy::type - nothrow_copy; - typedef typename mpl::or_< // reduces compile-time - nothrow_copy - , is_nothrow_move_constructible - >::type nothrow_move_constructor; - - assign_impl( - rhs_content - , nothrow_copy() - , nothrow_move_constructor() - , has_fallback_type_() - ); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) - private: - // silence MSVC warning C4512: assignment operator could not be generated - assigner& operator= (assigner const&); -#endif - }; - - friend class assigner; - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - // class move_assigner - // - // Internal visitor that "move assigns" the visited value to the given variant - // by appropriate destruction and move-construction. - // - - class move_assigner - : public assigner - { - public: // structors - - move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT - : assigner(lhs, rhs_which) - { - } - - private: // helpers, for internal visitor interface (below) - - template - void assign_impl( - RhsT& rhs_content - , mpl::true_ // has_nothrow_copy - , mpl::false_ // is_nothrow_move_constructible - , B2 // has_fallback_type - ) const BOOST_NOEXCEPT - { - assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2()); - } - - template - void assign_impl( - RhsT& rhs_content - , B // has_nothrow_copy - , mpl::true_ // is_nothrow_move_constructible - , B2 // has_fallback_type - ) const BOOST_NOEXCEPT - { - // ...destroy lhs's content... - assigner::lhs_.destroy_content(); // nothrow - - // ...move the rhs_content into lhs's storage... - new(assigner::lhs_.storage_.address()) - RhsT( detail::variant::move(rhs_content) ); // nothrow - - // ...and indicate new content type: - assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow - } - - template - void assign_impl( - RhsT& rhs_content - , mpl::false_ // has_nothrow_copy - , mpl::false_ // is_nothrow_move_constructible - , mpl::true_ // has_fallback_type - ) const - { - // Destroy lhs's content... - assigner::lhs_.destroy_content(); // nothrow - - BOOST_TRY - { - // ...and attempt to copy rhs's content into lhs's storage: - new(assigner::lhs_.storage_.address()) - RhsT( detail::variant::move(rhs_content) ); - } - BOOST_CATCH (...) - { - assigner::construct_fallback(); - - // ...and rethrow: - BOOST_RETHROW; - } - BOOST_CATCH_END - - // In the event of success, indicate new content type: - assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow - } - - template - void assign_impl( - RhsT& rhs_content - , mpl::false_ // has_nothrow_copy - , mpl::false_ // is_nothrow_move_constructible - , mpl::false_ // has_fallback_type - ) const - { - assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_()); - } - - public: // internal visitor interfaces - - template - void internal_visit(RhsT& rhs_content, int) const - { - typedef typename is_nothrow_move_constructible::type - nothrow_move_constructor; - typedef typename mpl::or_< // reduces compile-time - nothrow_move_constructor - , has_nothrow_copy - >::type nothrow_copy; - - assign_impl( - rhs_content - , nothrow_copy() - , nothrow_move_constructor() - , has_fallback_type_() - ); - } - -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) - private: - // silence MSVC warning C4512: assignment operator could not be generated - move_assigner& operator= (move_assigner const&); -#endif - }; - - friend class move_assigner; -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - void variant_assign(const variant& rhs) - { - // If the contained types are EXACTLY the same... - if (which_ == rhs.which_) - { - // ...then assign rhs's storage to lhs's content: - detail::variant::assign_storage visitor(rhs.storage_.address()); - this->internal_apply_visitor(visitor); - } - else - { - // Otherwise, perform general (copy-based) variant assignment: - assigner visitor(*this, rhs.which()); - rhs.internal_apply_visitor(visitor); - } - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - void variant_assign(variant&& rhs) - { - // If the contained types are EXACTLY the same... - if (which_ == rhs.which_) - { - // ...then move rhs's storage to lhs's content: - detail::variant::move_storage visitor(rhs.storage_.address()); - this->internal_apply_visitor(visitor); - } - else - { - // Otherwise, perform general (move-based) variant assignment: - move_assigner visitor(*this, rhs.which()); - rhs.internal_apply_visitor(visitor); - } - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - -private: // helpers, for modifiers (below) - - template - void assign(const T& rhs) - { - // If direct T-to-T assignment is not possible... - detail::variant::direct_assigner direct_assign(rhs); - if (this->apply_visitor(direct_assign) == false) - { - // ...then convert rhs to variant and assign: - // - // While potentially inefficient, the following construction of a - // variant allows T as any type convertible to one of the bounded - // types without excessive code redundancy. - // - variant temp(rhs); - variant_assign( detail::variant::move(temp) ); - } - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - template - void move_assign(T&& rhs) - { - // If direct T-to-T move assignment is not possible... - detail::variant::direct_mover direct_move(rhs); - if (this->apply_visitor(direct_move) == false) - { - // ...then convert rhs to variant and assign: - // - // While potentially inefficient, the following construction of a - // variant allows T as any type convertible to one of the bounded - // types without excessive code redundancy. - // - variant temp( detail::variant::move(rhs) ); - variant_assign( detail::variant::move(temp) ); - } - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - -public: // modifiers - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ - (!BOOST_WORKAROUND(BOOST_CLANG_VERSION, BOOST_TESTED_AT(150000)) || BOOST_CXX_VERSION <= 202002L) - template - typename boost::enable_if< - boost::mpl::and_< - boost::is_rvalue_reference, - mpl::not_< boost::is_const >, - boost::detail::variant::is_variant_constructible_from - >, - variant& - >::type operator=(T&& rhs) - { - move_assign( detail::variant::move(rhs) ); - return *this; - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - template - typename boost::enable_if< - mpl::or_< - boost::is_same, - boost::detail::variant::is_variant_constructible_from - >, - variant& - >::type operator=(const T& rhs) - { - assign(rhs); - return *this; - } - - // [MSVC6 requires copy assign appear after templated operator=] - variant& operator=(const variant& rhs) - { - variant_assign(rhs); - return *this; - } - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - variant& operator=(variant&& rhs) -#if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6) || defined(__clang__) - BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value) -#endif - { - variant_assign( detail::variant::move(rhs) ); - return *this; - } -#endif // BOOST_NO_CXX11_RVALUE_REFERENCES - - void swap(variant& rhs) - { - // If the contained types are the same... - if (which() == rhs.which()) - { - // ...then swap the values directly: - detail::variant::swap_with visitor(rhs); - this->apply_visitor(visitor); - } - else - { - // ...otherwise, perform general variant swap: - variant tmp( detail::variant::move(rhs) ); - rhs = detail::variant::move(*this); - *this = detail::variant::move(tmp); - } - } - -public: // queries - - // - // NOTE: member which() defined above. - // - - bool empty() const BOOST_NOEXCEPT - { - return false; - } - - const boost::typeindex::type_info& type() const - { - detail::variant::reflect visitor; - return this->apply_visitor(visitor); - } - -public: // prevent comparison with foreign types - - template - void operator==(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - - template - void operator<(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - - template - void operator!=(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - - template - void operator>(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - - template - void operator<=(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - - template - void operator>=(const U&) const - { - BOOST_STATIC_ASSERT( false && sizeof(U) ); - } - -public: // comparison operators - - // [MSVC6 requires these operators appear after template operators] - - bool operator==(const variant& rhs) const - { - if (this->which() != rhs.which()) - return false; - - detail::variant::comparer< - variant, detail::variant::equal_comp - > visitor(*this); - return rhs.apply_visitor(visitor); - } - - bool operator<(const variant& rhs) const - { - // - // Dirk Schreib suggested this collating order. - // - - if (this->which() != rhs.which()) - return this->which() < rhs.which(); - - detail::variant::comparer< - variant, detail::variant::less_comp - > visitor(*this); - return rhs.apply_visitor(visitor); - } - - /////////////////////////////////////////////////////////////////////////////// - // comparison operators != > <= >= - inline bool operator!=(const variant& rhs) const - { - return !(*this == rhs); - } - - inline bool operator>(const variant& rhs) const - { - return rhs < *this; - } - - inline bool operator<=(const variant& rhs) const - { - return !(*this > rhs); - } - - inline bool operator>=(const variant& rhs) const - { - return !(*this < rhs); - } - -// helpers, for visitation support (below) -- private when possible -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - - template < BOOST_VARIANT_ENUM_PARAMS(typename U) > - friend class variant; - -private: - -#else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - -public: - -#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - - template - BOOST_FORCEINLINE static typename Visitor::result_type - internal_apply_visitor_impl( - int internal_which - , int logical_which - , Visitor& visitor - , VoidPtrCV storage - ) - { - typedef mpl::int_<0> first_which; - typedef typename mpl::begin::type first_it; - typedef typename mpl::end::type last_it; - - typedef detail::variant::visitation_impl_step< - first_it, last_it - > first_step; - - return detail::variant::visitation_impl( - internal_which, logical_which - , visitor, storage, mpl::false_() - , never_uses_backup_flag() - , static_cast(0), static_cast(0) - ); - } - - template - BOOST_FORCEINLINE typename Visitor::result_type - internal_apply_visitor(Visitor& visitor) - { - return internal_apply_visitor_impl( - which_, which(), visitor, storage_.address() - ); - } - - template - BOOST_FORCEINLINE typename Visitor::result_type - internal_apply_visitor(Visitor& visitor) const - { - return internal_apply_visitor_impl( - which_, which(), visitor, storage_.address() - ); - } - -public: // visitation support - -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS - - template - typename Visitor::result_type - apply_visitor(Visitor& visitor) && - { - detail::variant::invoke_visitor invoker(visitor); - return this->internal_apply_visitor(invoker); - } - - template - typename Visitor::result_type - apply_visitor(Visitor& visitor) const&& - { - detail::variant::invoke_visitor invoker(visitor); - return this->internal_apply_visitor(invoker); - } - -#endif - - template - typename Visitor::result_type - apply_visitor(Visitor& visitor) -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS - & -#endif - { - detail::variant::invoke_visitor invoker(visitor); - return this->internal_apply_visitor(invoker); - } - - template - typename Visitor::result_type - apply_visitor(Visitor& visitor) const -#ifndef BOOST_NO_CXX11_REF_QUALIFIERS - & -#endif - { - detail::variant::invoke_visitor invoker(visitor); - return this->internal_apply_visitor(invoker); - } - -}; // class variant - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_variant_over -// -// See docs and boost/variant/variant_fwd.hpp for more information. -// -template -struct make_variant_over -{ -private: // precondition assertions - - BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence::value )); - typedef typename boost::mpl::insert_range< - boost::mpl::list<> - , boost::mpl::end< boost::mpl::list<> >::type - , Types - >::type copied_sequence_t; - -public: // metafunction result - - typedef variant< - detail::variant::over_sequence - > type; - -}; - -/////////////////////////////////////////////////////////////////////////////// -// function template swap -// -// Swaps two variants of the same type (i.e., identical specification). -// -template < BOOST_VARIANT_ENUM_PARAMS(typename T) > -inline void swap( - variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs - , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs - ) -{ - lhs.swap(rhs); -} - -} // namespace boost - -// implementation additions - -#if !defined(BOOST_NO_IOSTREAM) -#include -#endif // BOOST_NO_IOSTREAM - -#endif // BOOST_VARIANT_VARIANT_HPP diff --git a/boost/variant/variant_fwd.hpp b/boost/variant/variant_fwd.hpp deleted file mode 100644 index 613bcb6..0000000 --- a/boost/variant/variant_fwd.hpp +++ /dev/null @@ -1,322 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/variant_fwd.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2003 Eric Friedman, Itay Maman -// Copyright (c) 2013-2023 Antony Polukhin -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_VARIANT_FWD_HPP -#define BOOST_VARIANT_VARIANT_FWD_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT -// -// Defined if variant does not support make_variant_over (see below). -// -#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) -# define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT -#endif - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT -// -// Defined if make_recursive_variant cannot be supported as documented. -// -// Note: Currently, MPL lambda facility is used as workaround if defined, and -// so only types declared w/ MPL lambda workarounds will work. -// - -#include - -#if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \ - && !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) -# define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -// - -/* - GCC before 4.0 had no variadic tempaltes; - GCC 4.6 has incomplete implementation of variadic templates. - - MSVC2015 Update 1 has variadic templates, but they have issues. - - NOTE: Clang compiler defines __GNUC__ -*/ -#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \ - || (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) \ - || (defined(_MSC_VER) && (_MSC_VER <= 1900)) \ - || defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) \ - || defined (BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT) - -#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -# define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES -#endif - -#endif - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) -#include - -#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_class class)( -#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_typename typename)( - -#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_class class... -#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_typename typename... - -#define ARGS_VARIADER_1(x) x ## N... -#define ARGS_VARIADER_2(x) BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_ ## x ## N - -#define BOOST_VARIANT_MAKE_VARIADIC(sequence, x) BOOST_VARIANT_MAKE_VARIADIC_I(BOOST_PP_SEQ_SIZE(sequence), x) -#define BOOST_VARIANT_MAKE_VARIADIC_I(argscount, x) BOOST_VARIANT_MAKE_VARIADIC_II(argscount, x) -#define BOOST_VARIANT_MAKE_VARIADIC_II(argscount, orig) ARGS_VARIADER_ ## argscount(orig) - -/////////////////////////////////////////////////////////////////////////////// -// BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS -// -// Convenience macro for enumeration of variant params. -// When variadic templates are available expands: -// BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN -// BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN -// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... -// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN... -// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN -// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN -// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... -// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN... -// -// Rationale: Cleaner, simpler code for clients of variant library. Minimal -// code modifications to move from C++03 to C++11. -// -// With BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES defined -// will be used BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS from below `#else` -// - -#define BOOST_VARIANT_ENUM_PARAMS(x) \ - x ## 0, \ - BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ - /**/ - -#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS(x) \ - BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \ - /**/ - -#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_LIMIT_TYPES -// -// Implementation-defined preprocessor symbol describing the actual -// length of variant's pseudo-variadic template parameter list. -// -#include -#define BOOST_VARIANT_LIMIT_TYPES \ - BOOST_MPL_LIMIT_LIST_SIZE - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY -// -// Exposes maximum allowed arity of class templates with recursive_variant -// arguments. That is, -// make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >. -// -#include -#define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \ - BOOST_MPL_LIMIT_METAFUNCTION_ARITY - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_ENUM_PARAMS -// -// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params. -// -// Rationale: Cleaner, simpler code for clients of variant library. -// -#define BOOST_VARIANT_ENUM_PARAMS( param ) \ - BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) - -/////////////////////////////////////////////////////////////////////////////// -// macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS -// -// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params. -// -#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \ - BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param) - -#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround - - -namespace boost { - -namespace detail { namespace variant { - -/////////////////////////////////////////////////////////////////////////////// -// (detail) class void_ and class template convert_void -// -// Provides the mechanism by which void(NN) types are converted to -// mpl::void_ (and thus can be passed to mpl::list). -// -// Rationale: This is particularly needed for the using-declarations -// workaround (below), but also to avoid associating mpl namespace with -// variant in argument dependent lookups (which used to happen because of -// defaulting of template parameters to mpl::void_). -// - -struct void_; - -template -struct convert_void -{ - typedef T type; -}; - -template <> -struct convert_void< void_ > -{ - typedef mpl::na type; -}; - -/////////////////////////////////////////////////////////////////////////////// -// (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE -// -// Needed to work around compilers that don't support using-declaration -// overloads. (See the variant::initializer workarounds below.) -// - -#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) -// (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES) -// -// Defines void types that are each unique and specializations of -// convert_void that yields mpl::na for each voidNN type. -// - -#define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \ - struct BOOST_PP_CAT(void,N); \ - \ - template <> \ - struct convert_void< BOOST_PP_CAT(void,N) > \ - { \ - typedef mpl::na type; \ - }; \ - /**/ - -BOOST_PP_REPEAT( - BOOST_VARIANT_LIMIT_TYPES - , BOOST_VARIANT_DETAIL_DEFINE_VOID_N - , _ - ) - -#undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N - -#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround - -}} // namespace detail::variant - -#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) -# define BOOST_VARIANT_AUX_DECLARE_PARAMS BOOST_VARIANT_ENUM_PARAMS(typename T) -#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES) - -/////////////////////////////////////////////////////////////////////////////// -// (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM -// -// Template parameter list for variant and recursive_variant declarations. -// - -#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - -# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ - typename BOOST_PP_CAT(T,N) = detail::variant::void_ \ - /**/ - -#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) - -# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \ - typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \ - /**/ - -#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround - -#define BOOST_VARIANT_AUX_DECLARE_PARAMS \ - BOOST_PP_ENUM( \ - BOOST_VARIANT_LIMIT_TYPES \ - , BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \ - , T \ - ) \ - /**/ - -#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround - -/////////////////////////////////////////////////////////////////////////////// -// class template variant (concept inspired by Andrei Alexandrescu) -// -// Efficient, type-safe bounded discriminated union. -// -// Preconditions: -// - Each type must be unique. -// - No type may be const-qualified. -// -// Proper declaration form: -// variant (where types is a type-sequence) -// or -// variant (where T0 is NOT a type-sequence) -// -template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant; - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_recursive_variant -// -// Exposes a boost::variant with recursive_variant_ tags (below) substituted -// with the variant itself (wrapped as needed with boost::recursive_wrapper). -// -template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant; - -#undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL -#undef BOOST_VARIANT_AUX_DECLARE_PARAMS - -/////////////////////////////////////////////////////////////////////////////// -// type recursive_variant_ -// -// Tag type indicates where recursive variant substitution should occur. -// -#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT) - struct recursive_variant_ {}; -#else - typedef mpl::arg<1> recursive_variant_; -#endif - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_variant_over -// -// Result is a variant w/ types of the specified type sequence. -// -template struct make_variant_over; - -/////////////////////////////////////////////////////////////////////////////// -// metafunction make_recursive_variant_over -// -// Result is a recursive variant w/ types of the specified type sequence. -// -template struct make_recursive_variant_over; - -} // namespace boost - -#endif // BOOST_VARIANT_VARIANT_FWD_HPP diff --git a/boost/variant/visitor_ptr.hpp b/boost/variant/visitor_ptr.hpp deleted file mode 100644 index 0057841..0000000 --- a/boost/variant/visitor_ptr.hpp +++ /dev/null @@ -1,88 +0,0 @@ -//----------------------------------------------------------------------------- -// boost variant/visitor_ptr.hpp header file -// See http://www.boost.org for updates, documentation, and revision history. -//----------------------------------------------------------------------------- -// -// Copyright (c) 2002-2003 -// Eric Friedman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_VARIANT_VISITOR_PTR_HPP -#define BOOST_VARIANT_VISITOR_PTR_HPP - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace boost { - -////////////////////////////////////////////////////////////////////////// -// function template visitor_ptr -// -// Adapts a function pointer for use as visitor capable of handling -// values of a single type. Throws bad_visit if inappropriately applied. -// -template -class visitor_ptr_t - : public static_visitor -{ -private: // representation - - typedef R (*visitor_t)(T); - - visitor_t visitor_; - -public: // typedefs - - typedef R result_type; - -private: // private typedefs - - typedef typename mpl::eval_if< - is_reference - , mpl::identity - , add_reference - >::type argument_fwd_type; - -public: // structors - - explicit visitor_ptr_t(visitor_t visitor) BOOST_NOEXCEPT - : visitor_(visitor) - { - } - -public: // static visitor interfaces - - template - result_type operator()(const U&) const - { - boost::throw_exception(bad_visit()); - } - -public: // static visitor interfaces, cont. - - result_type operator()(argument_fwd_type operand) const - { - return visitor_(operand); - } - -}; - -template -inline visitor_ptr_t visitor_ptr(R (*visitor)(T)) -{ - return visitor_ptr_t(visitor); -} - -} // namespace boost - -#endif// BOOST_VISITOR_VISITOR_PTR_HPP diff --git a/boost/variant2/variant.hpp b/boost/variant2/variant.hpp index 7451eda..f0e8fef 100644 --- a/boost/variant2/variant.hpp +++ b/boost/variant2/variant.hpp @@ -920,6 +920,11 @@ template struct variant_base_impl this->emplace_impl( std::is_nothrow_constructible(), std::forward(a)... ); } + + static constexpr bool uses_double_storage() noexcept + { + return false; + } }; // trivially destructible, double buffered @@ -978,6 +983,11 @@ template struct variant_base_impl ix_ = J * 2 + i2; } + + static constexpr bool uses_double_storage() noexcept + { + return true; + } }; // not trivially destructible, single buffered @@ -1068,6 +1078,11 @@ template struct variant_base_impl st_.emplace( mp11::mp_size_t(), std::move(tmp) ); ix_ = J; } + + static constexpr bool uses_double_storage() noexcept + { + return false; + } }; // not trivially destructible, double buffered @@ -1193,6 +1208,11 @@ template struct variant_base_impl ix_ = J * 2 + i2; } + + static constexpr bool uses_double_storage() noexcept + { + return true; + } }; } // namespace detail @@ -1703,6 +1723,8 @@ public: using variant_base::index; + using variant_base::uses_double_storage; + // swap private: diff --git a/boost/version.hpp b/boost/version.hpp index 02bd3fc..c396009 100644 --- a/boost/version.hpp +++ b/boost/version.hpp @@ -19,7 +19,7 @@ // BOOST_VERSION / 100 % 1000 is the minor version // BOOST_VERSION / 100000 is the major version -#define BOOST_VERSION 108200 +#define BOOST_VERSION 108300 // // BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION @@ -27,6 +27,6 @@ // number, y is the minor version number, and z is the patch level if not 0. // This is used by to select which library version to link to. -#define BOOST_LIB_VERSION "1_82" +#define BOOST_LIB_VERSION "1_83" #endif diff --git a/boost/visit_each.hpp b/boost/visit_each.hpp deleted file mode 100644 index 6463ca9..0000000 --- a/boost/visit_each.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Boost.Signals library - -// Copyright Douglas Gregor 2001-2003. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org/libs/signals - -#ifndef BOOST_VISIT_EACH_HPP -#define BOOST_VISIT_EACH_HPP - -namespace boost { - template - inline void visit_each(Visitor& visitor, const T& t, long) - { - visitor(t); - } - - template - inline void visit_each(Visitor& visitor, const T& t) - { - visit_each(visitor, t, 0); - } -} - -#endif // BOOST_VISIT_EACH_HPP diff --git a/boost/winapi/bcrypt.hpp b/boost/winapi/bcrypt.hpp new file mode 100644 index 0000000..d476b76 --- /dev/null +++ b/boost/winapi/bcrypt.hpp @@ -0,0 +1,89 @@ +/* + * Copyright 2017 James E. King, III + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_BCRYPT_HPP_INCLUDED_ +#define BOOST_WINAPI_BCRYPT_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if defined(BOOST_USE_WINDOWS_H) +#include +#endif + +#include + +#if defined(BOOST_USE_WINDOWS_H) + +namespace boost { namespace winapi { +typedef ::BCRYPT_ALG_HANDLE BCRYPT_ALG_HANDLE_; +}} + +#else // defined(BOOST_USE_WINDOWS_H) + +namespace boost { namespace winapi { +typedef PVOID_ BCRYPT_ALG_HANDLE_; +}} + +extern "C" { + +boost::winapi::NTSTATUS_ BOOST_WINAPI_WINAPI_CC +BCryptCloseAlgorithmProvider( + boost::winapi::BCRYPT_ALG_HANDLE_ hAlgorithm, + boost::winapi::ULONG_ dwFlags +); + +boost::winapi::NTSTATUS_ BOOST_WINAPI_WINAPI_CC +BCryptGenRandom( + boost::winapi::BCRYPT_ALG_HANDLE_ hAlgorithm, + boost::winapi::PUCHAR_ pbBuffer, + boost::winapi::ULONG_ cbBuffer, + boost::winapi::ULONG_ dwFlags +); + +boost::winapi::NTSTATUS_ BOOST_WINAPI_WINAPI_CC +BCryptOpenAlgorithmProvider( + boost::winapi::BCRYPT_ALG_HANDLE_ *phAlgorithm, + boost::winapi::LPCWSTR_ pszAlgId, + boost::winapi::LPCWSTR_ pszImplementation, + boost::winapi::DWORD_ dwFlags +); + +} // extern "C" + +#endif // defined(BOOST_USE_WINDOWS_H) + +namespace boost { +namespace winapi { + +#if defined(BOOST_USE_WINDOWS_H) +const WCHAR_ BCRYPT_RNG_ALGORITHM_[] = BCRYPT_RNG_ALGORITHM; +#else +const WCHAR_ BCRYPT_RNG_ALGORITHM_[] = L"RNG"; +#endif + +using ::BCryptCloseAlgorithmProvider; +using ::BCryptGenRandom; +using ::BCryptOpenAlgorithmProvider; + +} // winapi +} // boost + +#include + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#endif // BOOST_WINAPI_BCRYPT_HPP_INCLUDED_ diff --git a/boost/winapi/condition_variable.hpp b/boost/winapi/condition_variable.hpp new file mode 100644 index 0000000..883cd21 --- /dev/null +++ b/boost/winapi/condition_variable.hpp @@ -0,0 +1,123 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_CONDITION_VARIABLE_HPP_INCLUDED_ +#define BOOST_WINAPI_CONDITION_VARIABLE_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#include +#include + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { +struct _RTL_CONDITION_VARIABLE; +struct _RTL_CRITICAL_SECTION; +struct _RTL_SRWLOCK; + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +InitializeConditionVariable(::_RTL_CONDITION_VARIABLE* ConditionVariable); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +WakeConditionVariable(::_RTL_CONDITION_VARIABLE* ConditionVariable); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +WakeAllConditionVariable(::_RTL_CONDITION_VARIABLE* ConditionVariable); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +SleepConditionVariableCS( + ::_RTL_CONDITION_VARIABLE* ConditionVariable, + ::_RTL_CRITICAL_SECTION* CriticalSection, + boost::winapi::DWORD_ dwMilliseconds); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +SleepConditionVariableSRW( + ::_RTL_CONDITION_VARIABLE* ConditionVariable, + ::_RTL_SRWLOCK* SRWLock, + boost::winapi::DWORD_ dwMilliseconds, + boost::winapi::ULONG_ Flags); +} +#endif + +namespace boost { +namespace winapi { + +typedef struct BOOST_MAY_ALIAS _RTL_CONDITION_VARIABLE { + PVOID_ Ptr; +} CONDITION_VARIABLE_, *PCONDITION_VARIABLE_; + +#if defined( BOOST_USE_WINDOWS_H ) +#define BOOST_WINAPI_CONDITION_VARIABLE_INIT CONDITION_VARIABLE_INIT +#else +#define BOOST_WINAPI_CONDITION_VARIABLE_INIT {0} +#endif + +struct _RTL_CRITICAL_SECTION; +struct _RTL_SRWLOCK; + +BOOST_FORCEINLINE VOID_ InitializeConditionVariable(PCONDITION_VARIABLE_ ConditionVariable) +{ + ::InitializeConditionVariable(reinterpret_cast< ::_RTL_CONDITION_VARIABLE* >(ConditionVariable)); +} + +BOOST_FORCEINLINE VOID_ WakeConditionVariable(PCONDITION_VARIABLE_ ConditionVariable) +{ + ::WakeConditionVariable(reinterpret_cast< ::_RTL_CONDITION_VARIABLE* >(ConditionVariable)); +} + +BOOST_FORCEINLINE VOID_ WakeAllConditionVariable(PCONDITION_VARIABLE_ ConditionVariable) +{ + ::WakeAllConditionVariable(reinterpret_cast< ::_RTL_CONDITION_VARIABLE* >(ConditionVariable)); +} + +BOOST_FORCEINLINE BOOL_ SleepConditionVariableCS( + PCONDITION_VARIABLE_ ConditionVariable, + _RTL_CRITICAL_SECTION* CriticalSection, + DWORD_ dwMilliseconds) +{ + return ::SleepConditionVariableCS( + reinterpret_cast< ::_RTL_CONDITION_VARIABLE* >(ConditionVariable), + reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(CriticalSection), + dwMilliseconds); +} + +BOOST_FORCEINLINE BOOL_ SleepConditionVariableSRW( + PCONDITION_VARIABLE_ ConditionVariable, + _RTL_SRWLOCK* SRWLock, + DWORD_ dwMilliseconds, + ULONG_ Flags) +{ + return ::SleepConditionVariableSRW( + reinterpret_cast< ::_RTL_CONDITION_VARIABLE* >(ConditionVariable), + reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock), + dwMilliseconds, + Flags); +} + +#if defined( BOOST_USE_WINDOWS_H ) +BOOST_CONSTEXPR_OR_CONST ULONG_ CONDITION_VARIABLE_LOCKMODE_SHARED_ = CONDITION_VARIABLE_LOCKMODE_SHARED; +#else // defined( BOOST_USE_WINDOWS_H ) +BOOST_CONSTEXPR_OR_CONST ULONG_ CONDITION_VARIABLE_LOCKMODE_SHARED_ = 0x00000001; +#endif // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST ULONG_ condition_variable_lockmode_shared = CONDITION_VARIABLE_LOCKMODE_SHARED_; + +} +} + +#include + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#endif // BOOST_WINAPI_CONDITION_VARIABLE_HPP_INCLUDED_ diff --git a/boost/winapi/critical_section.hpp b/boost/winapi/critical_section.hpp new file mode 100644 index 0000000..ac850d3 --- /dev/null +++ b/boost/winapi/critical_section.hpp @@ -0,0 +1,240 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_CRITICAL_SECTION_HPP_INCLUDED_ +#define BOOST_WINAPI_CRITICAL_SECTION_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) + +extern "C" { +#if !defined( BOOST_WINAPI_IS_MINGW ) + +// Windows CE uses a different name for the structure +#if defined (_WIN32_WCE) +struct CRITICAL_SECTION; +namespace boost { +namespace winapi { +namespace detail { + typedef CRITICAL_SECTION winsdk_critical_section; +} +} +} +#else +struct _RTL_CRITICAL_SECTION; +namespace boost { +namespace winapi { +namespace detail { + typedef _RTL_CRITICAL_SECTION winsdk_critical_section; +} +} +} +#endif + +#else +// MinGW uses a different name for the structure +struct _CRITICAL_SECTION; + +namespace boost { +namespace winapi { +namespace detail { + typedef _CRITICAL_SECTION winapi_critical_section; +} +} +} +#endif + +#if !defined( BOOST_WINAPI_IS_MINGW ) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSection(boost::winapi::detail::winsdk_critical_section* lpCriticalSection); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +EnterCriticalSection(boost::winapi::detail::winsdk_critical_section* lpCriticalSection); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +LeaveCriticalSection(boost::winapi::detail::winsdk_critical_section* lpCriticalSection); + +#if BOOST_USE_WINAPI_VERSION >= 0x0403 +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSectionAndSpinCount( + boost::winapi::detail::winsdk_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount); + +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +SetCriticalSectionSpinCount( + boost::winapi::detail::winsdk_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount); +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSectionEx( + boost::winapi::detail::winsdk_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount, + boost::winapi::DWORD_ Flags); +#endif +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +TryEnterCriticalSection(boost::winapi::detail::winsdk_critical_section* lpCriticalSection); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +DeleteCriticalSection(boost::winapi::detail::winsdk_critical_section* lpCriticalSection); + +#else // defined( BOOST_WINAPI_IS_MINGW ) + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSection(boost::winapi::detail::winapi_critical_section* lpCriticalSection); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +EnterCriticalSection(boost::winapi::detail::winapi_critical_section* lpCriticalSection); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +LeaveCriticalSection(boost::winapi::detail::winapi_critical_section* lpCriticalSection); + +#if BOOST_USE_WINAPI_VERSION >= 0x0403 +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSectionAndSpinCount( + boost::winapi::detail::winapi_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount); + +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +SetCriticalSectionSpinCount( + boost::winapi::detail::winapi_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount); +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +InitializeCriticalSectionEx( + boost::winapi::detail::winapi_critical_section* lpCriticalSection, + boost::winapi::DWORD_ dwSpinCount, + boost::winapi::DWORD_ Flags); +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +TryEnterCriticalSection(boost::winapi::detail::winapi_critical_section* lpCriticalSection); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +DeleteCriticalSection(boost::winapi::detail::winapi_critical_section* lpCriticalSection); + +#endif // defined( BOOST_WINAPI_IS_MINGW ) +} // extern "C" +#endif + +namespace boost { +namespace winapi { + + +#pragma pack(push, 8) + +#if !defined(_WIN32_WCE) + +struct _RTL_CRITICAL_SECTION_DEBUG; + +typedef struct BOOST_MAY_ALIAS _RTL_CRITICAL_SECTION { + _RTL_CRITICAL_SECTION_DEBUG* DebugInfo; + LONG_ LockCount; + LONG_ RecursionCount; + HANDLE_ OwningThread; + HANDLE_ LockSemaphore; + ULONG_PTR_ SpinCount; +} CRITICAL_SECTION_, *PCRITICAL_SECTION_; + +#else + +// Windows CE has different layout +typedef struct BOOST_MAY_ALIAS CRITICAL_SECTION { + unsigned int LockCount; + HANDLE OwnerThread; + HANDLE hCrit; + DWORD needtrap; + DWORD dwContentions; +} CRITICAL_SECTION_, *LPCRITICAL_SECTION_; + +#endif + +#pragma pack(pop) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_FORCEINLINE VOID_ InitializeCriticalSection(CRITICAL_SECTION_* lpCriticalSection) +{ + ::InitializeCriticalSection(winapi::detail::cast_ptr(lpCriticalSection)); +} +#endif + +BOOST_FORCEINLINE VOID_ EnterCriticalSection(CRITICAL_SECTION_* lpCriticalSection) +{ + ::EnterCriticalSection(winapi::detail::cast_ptr(lpCriticalSection)); +} + +BOOST_FORCEINLINE VOID_ LeaveCriticalSection(CRITICAL_SECTION_* lpCriticalSection) +{ + ::LeaveCriticalSection(winapi::detail::cast_ptr(lpCriticalSection)); +} + +#if BOOST_USE_WINAPI_VERSION >= 0x0403 +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_FORCEINLINE BOOL_ InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION_* lpCriticalSection, DWORD_ dwSpinCount) +{ + return ::InitializeCriticalSectionAndSpinCount(winapi::detail::cast_ptr(lpCriticalSection), dwSpinCount); +} + +BOOST_FORCEINLINE DWORD_ SetCriticalSectionSpinCount(CRITICAL_SECTION_* lpCriticalSection, DWORD_ dwSpinCount) +{ + return ::SetCriticalSectionSpinCount(winapi::detail::cast_ptr(lpCriticalSection), dwSpinCount); +} +#endif + +// CRITICAL_SECTION_NO_DEBUG_INFO is defined for WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) +BOOST_CONSTEXPR_OR_CONST DWORD_ CRITICAL_SECTION_NO_DEBUG_INFO_ = 0x01000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRITICAL_SECTION_FLAG_NO_DEBUG_INFO_ = CRITICAL_SECTION_NO_DEBUG_INFO_; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRITICAL_SECTION_FLAG_DYNAMIC_SPIN_ = 0x02000000; // undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ CRITICAL_SECTION_FLAG_STATIC_INIT_ = 0x04000000; // undocumented + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_FORCEINLINE BOOL_ InitializeCriticalSectionEx(CRITICAL_SECTION_* lpCriticalSection, DWORD_ dwSpinCount, DWORD_ Flags) +{ + return ::InitializeCriticalSectionEx(winapi::detail::cast_ptr(lpCriticalSection), dwSpinCount, Flags); +} +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +#endif // BOOST_USE_WINAPI_VERSION >= 0x0403 + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 +BOOST_FORCEINLINE BOOL_ TryEnterCriticalSection(CRITICAL_SECTION_* lpCriticalSection) +{ + return ::TryEnterCriticalSection(winapi::detail::cast_ptr(lpCriticalSection)); +} +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 + +BOOST_FORCEINLINE VOID_ DeleteCriticalSection(CRITICAL_SECTION_* lpCriticalSection) +{ + ::DeleteCriticalSection(winapi::detail::cast_ptr(lpCriticalSection)); +} + +} +} + +#include + +#endif // BOOST_WINAPI_CRITICAL_SECTION_HPP_INCLUDED_ diff --git a/boost/winapi/crypt.hpp b/boost/winapi/crypt.hpp new file mode 100644 index 0000000..12b7499 --- /dev/null +++ b/boost/winapi/crypt.hpp @@ -0,0 +1,191 @@ +/* + * Copyright 2014 Antony Polukhin + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_CRYPT_HPP_INCLUDED_ +#define BOOST_WINAPI_CRYPT_HPP_INCLUDED_ + +#include +#if defined( BOOST_USE_WINDOWS_H ) +// This header is not always included as part of windows.h +#include +#endif +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +namespace boost { namespace winapi { +typedef ULONG_PTR_ HCRYPTPROV_; +}} + +extern "C" { +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptEnumProvidersA( + boost::winapi::DWORD_ dwIndex, + boost::winapi::DWORD_ *pdwReserved, + boost::winapi::DWORD_ dwFlags, + boost::winapi::DWORD_ *pdwProvType, + boost::winapi::LPSTR_ szProvName, + boost::winapi::DWORD_ *pcbProvName); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptAcquireContextA( + boost::winapi::HCRYPTPROV_ *phProv, + boost::winapi::LPCSTR_ pszContainer, + boost::winapi::LPCSTR_ pszProvider, + boost::winapi::DWORD_ dwProvType, + boost::winapi::DWORD_ dwFlags); +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptEnumProvidersW( + boost::winapi::DWORD_ dwIndex, + boost::winapi::DWORD_ *pdwReserved, + boost::winapi::DWORD_ dwFlags, + boost::winapi::DWORD_ *pdwProvType, + boost::winapi::LPWSTR_ szProvName, + boost::winapi::DWORD_ *pcbProvName); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptAcquireContextW( + boost::winapi::HCRYPTPROV_ *phProv, + boost::winapi::LPCWSTR_ szContainer, + boost::winapi::LPCWSTR_ szProvider, + boost::winapi::DWORD_ dwProvType, + boost::winapi::DWORD_ dwFlags); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptGenRandom( + boost::winapi::HCRYPTPROV_ hProv, + boost::winapi::DWORD_ dwLen, + boost::winapi::BYTE_ *pbBuffer); +#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +#if defined(_MSC_VER) && (_MSC_VER+0) >= 1500 && (_MSC_VER+0) < 1900 && BOOST_USE_NTDDI_VERSION < BOOST_WINAPI_NTDDI_WINXP +// Standalone MS Windows SDK 6.0A and later until 10.0 provide a different declaration of CryptReleaseContext for Windows 2000 and older. +// This is not the case for (a) MinGW and MinGW-w64, (b) MSVC 7.1 and 8, which are shipped with their own Windows SDK, +// and (c) MSVC 14.0 and later, which are used with Windows SDK 10. +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptReleaseContext( + boost::winapi::HCRYPTPROV_ hProv, + boost::winapi::ULONG_PTR_ dwFlags); +#else +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +CryptReleaseContext( + boost::winapi::HCRYPTPROV_ hProv, + boost::winapi::DWORD_ dwFlags); +#endif +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM +} +#endif // !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +typedef ::HCRYPTPROV HCRYPTPROV_; + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_CONSTEXPR_OR_CONST DWORD_ PROV_RSA_FULL_ = PROV_RSA_FULL; + +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_VERIFYCONTEXT_ = CRYPT_VERIFYCONTEXT; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_NEWKEYSET_ = CRYPT_NEWKEYSET; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_DELETEKEYSET_ = CRYPT_DELETEKEYSET; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_MACHINE_KEYSET_ = CRYPT_MACHINE_KEYSET; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_SILENT_ = CRYPT_SILENT; +#endif + +#else + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_CONSTEXPR_OR_CONST DWORD_ PROV_RSA_FULL_ = 1; + +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_VERIFYCONTEXT_ = 0xF0000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_NEWKEYSET_ = 8; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_DELETEKEYSET_ = 16; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_MACHINE_KEYSET_ = 32; +BOOST_CONSTEXPR_OR_CONST DWORD_ CRYPT_SILENT_ = 64; +#endif + +#endif + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#if !defined( BOOST_NO_ANSI_APIS ) +using ::CryptEnumProvidersA; +using ::CryptAcquireContextA; +#endif +using ::CryptEnumProvidersW; +using ::CryptAcquireContextW; +using ::CryptGenRandom; + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE BOOL_ crypt_enum_providers( + DWORD_ dwIndex, + DWORD_ *pdwReserved, + DWORD_ dwFlags, + DWORD_ *pdwProvType, + LPSTR_ szProvName, + DWORD_ *pcbProvName) +{ + return ::CryptEnumProvidersA(dwIndex, pdwReserved, dwFlags, pdwProvType, szProvName, pcbProvName); +} + +BOOST_FORCEINLINE BOOL_ crypt_acquire_context( + HCRYPTPROV_ *phProv, + LPCSTR_ pszContainer, + LPCSTR_ pszProvider, + DWORD_ dwProvType, + DWORD_ dwFlags) +{ + return ::CryptAcquireContextA(phProv, pszContainer, pszProvider, dwProvType, dwFlags); +} +#endif + +BOOST_FORCEINLINE BOOL_ crypt_enum_providers( + DWORD_ dwIndex, + DWORD_ *pdwReserved, + DWORD_ dwFlags, + DWORD_ *pdwProvType, + LPWSTR_ szProvName, + DWORD_ *pcbProvName) +{ + return ::CryptEnumProvidersW(dwIndex, pdwReserved, dwFlags, pdwProvType, szProvName, pcbProvName); +} + +BOOST_FORCEINLINE BOOL_ crypt_acquire_context( + HCRYPTPROV_ *phProv, + LPCWSTR_ szContainer, + LPCWSTR_ szProvider, + DWORD_ dwProvType, + DWORD_ dwFlags) +{ + return ::CryptAcquireContextW(phProv, szContainer, szProvider, dwProvType, dwFlags); +} + +#endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_FORCEINLINE BOOL_ CryptReleaseContext(HCRYPTPROV_ hProv, DWORD_ dwFlags) +{ + return ::CryptReleaseContext(hProv, dwFlags); +} +#endif + +} +} + +#include + +#endif // BOOST_WINAPI_CRYPT_HPP_INCLUDED_ diff --git a/boost/winapi/detail/cast_ptr.hpp b/boost/winapi/detail/cast_ptr.hpp new file mode 100644 index 0000000..4e089b3 --- /dev/null +++ b/boost/winapi/detail/cast_ptr.hpp @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_DETAIL_CAST_PTR_HPP_INCLUDED_ +#define BOOST_WINAPI_DETAIL_CAST_PTR_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace winapi { +namespace detail { + +//! This class is used to automatically cast pointers to the type used in the current Windows SDK function declarations +class cast_ptr +{ +private: + const void* m_p; + +public: + explicit BOOST_FORCEINLINE cast_ptr(const void* p) BOOST_NOEXCEPT : m_p(p) {} + template< typename T > + BOOST_FORCEINLINE operator T* () const BOOST_NOEXCEPT { return (T*)m_p; } +}; + +} +} +} + +#include + +#endif // BOOST_WINAPI_DETAIL_CAST_PTR_HPP_INCLUDED_ diff --git a/boost/winapi/get_current_process_id.hpp b/boost/winapi/get_current_process_id.hpp new file mode 100644 index 0000000..b1a3ea1 --- /dev/null +++ b/boost/winapi/get_current_process_id.hpp @@ -0,0 +1,33 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_GET_CURRENT_PROCESS_ID_HPP_INCLUDED_ +#define BOOST_WINAPI_GET_CURRENT_PROCESS_ID_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Windows CE define GetCurrentProcessId as an inline function in kfuncs.h +#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE ) +extern "C" { +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC GetCurrentProcessId(BOOST_WINAPI_DETAIL_VOID); +} +#endif + +namespace boost { +namespace winapi { +using ::GetCurrentProcessId; +} +} + +#include + +#endif // BOOST_WINAPI_GET_CURRENT_PROCESS_ID_HPP_INCLUDED_ diff --git a/boost/winapi/get_current_thread_id.hpp b/boost/winapi/get_current_thread_id.hpp new file mode 100644 index 0000000..6f78f55 --- /dev/null +++ b/boost/winapi/get_current_thread_id.hpp @@ -0,0 +1,34 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_GET_CURRENT_THREAD_ID_HPP_INCLUDED_ +#define BOOST_WINAPI_GET_CURRENT_THREAD_ID_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +// Windows CE define GetCurrentThreadId as an inline function in kfuncs.h +#if !defined( BOOST_USE_WINDOWS_H ) && !defined( UNDER_CE ) +extern "C" { +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC GetCurrentThreadId(BOOST_WINAPI_DETAIL_VOID); +} +#endif + +namespace boost { +namespace winapi { +using ::GetCurrentThreadId; +} +} + +#include + +#endif // BOOST_WINAPI_GET_CURRENT_THREAD_ID_HPP_INCLUDED_ diff --git a/boost/winapi/pipes.hpp b/boost/winapi/pipes.hpp new file mode 100644 index 0000000..5d02131 --- /dev/null +++ b/boost/winapi/pipes.hpp @@ -0,0 +1,322 @@ +/* + * Copyright 2016 Klemens D. Morgenstern + * Copyright 2016, 2017 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_PIPES_HPP_INCLUDED_ +#define BOOST_WINAPI_PIPES_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#include + +#if !defined( BOOST_USE_WINDOWS_H ) && BOOST_WINAPI_PARTITION_DESKTOP && !defined( BOOST_NO_ANSI_APIS ) +extern "C" { +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateNamedPipeA( + boost::winapi::LPCSTR_ lpName, + boost::winapi::DWORD_ dwOpenMode, + boost::winapi::DWORD_ dwPipeMode, + boost::winapi::DWORD_ nMaxInstances, + boost::winapi::DWORD_ nOutBufferSize, + boost::winapi::DWORD_ nInBufferSize, + boost::winapi::DWORD_ nDefaultTimeOut, + _SECURITY_ATTRIBUTES *lpSecurityAttributes); +} // extern "C" +#endif // !defined( BOOST_USE_WINDOWS_H ) && BOOST_WINAPI_PARTITION_DESKTOP && !defined( BOOST_NO_ANSI_APIS ) + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ImpersonateNamedPipeClient( + boost::winapi::HANDLE_ hNamedPipe); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CreatePipe( + boost::winapi::PHANDLE_ hReadPipe, + boost::winapi::PHANDLE_ hWritePipe, + _SECURITY_ATTRIBUTES* lpPipeAttributes, + boost::winapi::DWORD_ nSize); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ConnectNamedPipe( + boost::winapi::HANDLE_ hNamedPipe, + _OVERLAPPED* lpOverlapped); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC DisconnectNamedPipe( + boost::winapi::HANDLE_ hNamedPipe); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC SetNamedPipeHandleState( + boost::winapi::HANDLE_ hNamedPipe, + boost::winapi::LPDWORD_ lpMode, + boost::winapi::LPDWORD_ lpMaxCollectionCount, + boost::winapi::LPDWORD_ lpCollectDataTimeout); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC PeekNamedPipe( + boost::winapi::HANDLE_ hNamedPipe, + boost::winapi::LPVOID_ lpBuffer, + boost::winapi::DWORD_ nBufferSize, + boost::winapi::LPDWORD_ lpBytesRead, + boost::winapi::LPDWORD_ lpTotalBytesAvail, + boost::winapi::LPDWORD_ lpBytesLeftThisMessage); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC TransactNamedPipe( + boost::winapi::HANDLE_ hNamedPipe, + boost::winapi::LPVOID_ lpInBuffer, + boost::winapi::DWORD_ nInBufferSize, + boost::winapi::LPVOID_ lpOutBuffer, + boost::winapi::DWORD_ nOutBufferSize, + boost::winapi::LPDWORD_ lpBytesRead, + _OVERLAPPED* lpOverlapped); + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC WaitNamedPipeA( + boost::winapi::LPCSTR_ lpNamedPipeName, + boost::winapi::DWORD_ nTimeOut); +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC CreateNamedPipeW( + boost::winapi::LPCWSTR_ lpName, + boost::winapi::DWORD_ dwOpenMode, + boost::winapi::DWORD_ dwPipeMode, + boost::winapi::DWORD_ nMaxInstances, + boost::winapi::DWORD_ nOutBufferSize, + boost::winapi::DWORD_ nInBufferSize, + boost::winapi::DWORD_ nDefaultTimeOut, + _SECURITY_ATTRIBUTES* lpSecurityAttributes); + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC WaitNamedPipeW( + boost::winapi::LPCWSTR_ lpNamedPipeName, + boost::winapi::DWORD_ nTimeOut); + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetNamedPipeClientComputerNameA( + boost::winapi::HANDLE_ Pipe, + boost::winapi::LPSTR_ ClientComputerName, + boost::winapi::ULONG_ ClientComputerNameLength); +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetNamedPipeClientComputerNameW( + boost::winapi::HANDLE_ Pipe, + boost::winapi::LPWSTR_ ClientComputerName, + boost::winapi::ULONG_ ClientComputerNameLength); +#endif + +} // extern "C" +#endif // !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_DUPLEX_ = PIPE_ACCESS_DUPLEX; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_INBOUND_ = PIPE_ACCESS_INBOUND; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_OUTBOUND_ = PIPE_ACCESS_OUTBOUND; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_TYPE_BYTE_ = PIPE_TYPE_BYTE; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_TYPE_MESSAGE_ = PIPE_TYPE_MESSAGE; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_READMODE_BYTE_ = PIPE_READMODE_BYTE; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_READMODE_MESSAGE_ = PIPE_READMODE_MESSAGE; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_WAIT_ = PIPE_WAIT; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_NOWAIT_ = PIPE_NOWAIT; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_UNLIMITED_INSTANCES_ = PIPE_UNLIMITED_INSTANCES; + +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_USE_DEFAULT_WAIT_ = NMPWAIT_USE_DEFAULT_WAIT; +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_NOWAIT_ = NMPWAIT_NOWAIT; +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_WAIT_FOREVER_ = NMPWAIT_WAIT_FOREVER; + +#else // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_DUPLEX_ = 0x00000003; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_INBOUND_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCESS_OUTBOUND_ = 0x00000002; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_TYPE_BYTE_ = 0x00000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_TYPE_MESSAGE_ = 0x00000004; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_READMODE_BYTE_ = 0x00000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_READMODE_MESSAGE_ = 0x00000002; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_WAIT_ = 0x00000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_NOWAIT_ = 0x00000001; + +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_UNLIMITED_INSTANCES_ = 255u; + +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_USE_DEFAULT_WAIT_ = 0x00000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_NOWAIT_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ NMPWAIT_WAIT_FOREVER_ = 0xFFFFFFFF; + +#endif // defined( BOOST_USE_WINDOWS_H ) + +// These constants are not defined in Windows SDK prior to 7.0A +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_ACCEPT_REMOTE_CLIENTS_ = 0x00000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PIPE_REJECT_REMOTE_CLIENTS_ = 0x00000008; + +using ::ImpersonateNamedPipeClient; +using ::DisconnectNamedPipe; +using ::SetNamedPipeHandleState; +using ::PeekNamedPipe; + +#if !defined( BOOST_NO_ANSI_APIS ) +using ::WaitNamedPipeA; +#endif +using ::WaitNamedPipeW; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +#if !defined( BOOST_NO_ANSI_APIS ) +using ::GetNamedPipeClientComputerNameA; +#endif // !defined( BOOST_NO_ANSI_APIS ) +using ::GetNamedPipeClientComputerNameW; +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +BOOST_FORCEINLINE BOOL_ CreatePipe(PHANDLE_ hReadPipe, PHANDLE_ hWritePipe, LPSECURITY_ATTRIBUTES_ lpPipeAttributes, DWORD_ nSize) +{ + return ::CreatePipe(hReadPipe, hWritePipe, reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpPipeAttributes), nSize); +} + +BOOST_FORCEINLINE BOOL_ ConnectNamedPipe(HANDLE_ hNamedPipe, LPOVERLAPPED_ lpOverlapped) +{ + return ::ConnectNamedPipe(hNamedPipe, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} + +BOOST_FORCEINLINE BOOL_ TransactNamedPipe(HANDLE_ hNamedPipe, LPVOID_ lpInBuffer, DWORD_ nInBufferSize, LPVOID_ lpOutBuffer, DWORD_ nOutBufferSize, LPDWORD_ lpBytesRead, LPOVERLAPPED_ lpOverlapped) +{ + return ::TransactNamedPipe(hNamedPipe, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, reinterpret_cast< ::_OVERLAPPED* >(lpOverlapped)); +} + + +#if BOOST_WINAPI_PARTITION_DESKTOP && !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE HANDLE_ CreateNamedPipeA( + LPCSTR_ lpName, + DWORD_ dwOpenMode, + DWORD_ dwPipeMode, + DWORD_ nMaxInstances, + DWORD_ nOutBufferSize, + DWORD_ nInBufferSize, + DWORD_ nDefaultTimeOut, + LPSECURITY_ATTRIBUTES_ lpSecurityAttributes) +{ + return ::CreateNamedPipeA( + lpName, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes)); +} + +BOOST_FORCEINLINE HANDLE_ create_named_pipe( + LPCSTR_ lpName, + DWORD_ dwOpenMode, + DWORD_ dwPipeMode, + DWORD_ nMaxInstances, + DWORD_ nOutBufferSize, + DWORD_ nInBufferSize, + DWORD_ nDefaultTimeOut, + LPSECURITY_ATTRIBUTES_ lpSecurityAttributes) +{ + return ::CreateNamedPipeA( + lpName, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes)); +} +#endif // BOOST_WINAPI_PARTITION_DESKTOP && !defined( BOOST_NO_ANSI_APIS ) + +BOOST_FORCEINLINE HANDLE_ CreateNamedPipeW( + LPCWSTR_ lpName, + DWORD_ dwOpenMode, + DWORD_ dwPipeMode, + DWORD_ nMaxInstances, + DWORD_ nOutBufferSize, + DWORD_ nInBufferSize, + DWORD_ nDefaultTimeOut, + LPSECURITY_ATTRIBUTES_ lpSecurityAttributes) +{ + return ::CreateNamedPipeW( + lpName, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes)); +} + +BOOST_FORCEINLINE HANDLE_ create_named_pipe( + LPCWSTR_ lpName, + DWORD_ dwOpenMode, + DWORD_ dwPipeMode, + DWORD_ nMaxInstances, + DWORD_ nOutBufferSize, + DWORD_ nInBufferSize, + DWORD_ nDefaultTimeOut, + LPSECURITY_ATTRIBUTES_ lpSecurityAttributes) +{ + return ::CreateNamedPipeW( + lpName, + dwOpenMode, + dwPipeMode, + nMaxInstances, + nOutBufferSize, + nInBufferSize, + nDefaultTimeOut, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSecurityAttributes)); +} + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE BOOL_ wait_named_pipe(LPCSTR_ lpNamedPipeName, DWORD_ nTimeOut) +{ + return ::WaitNamedPipeA(lpNamedPipeName, nTimeOut); +} +#endif //BOOST_NO_ANSI_APIS + +BOOST_FORCEINLINE BOOL_ wait_named_pipe(LPCWSTR_ lpNamedPipeName, DWORD_ nTimeOut) +{ + return ::WaitNamedPipeW(lpNamedPipeName, nTimeOut); +} + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE BOOL_ get_named_pipe_client_computer_name(HANDLE_ Pipe, LPSTR_ ClientComputerName, ULONG_ ClientComputerNameLength) +{ + return ::GetNamedPipeClientComputerNameA(Pipe, ClientComputerName, ClientComputerNameLength); +} +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_FORCEINLINE BOOL_ get_named_pipe_client_computer_name(HANDLE_ Pipe, LPWSTR_ ClientComputerName, ULONG_ ClientComputerNameLength) +{ + return ::GetNamedPipeClientComputerNameW(Pipe, ClientComputerName, ClientComputerNameLength); +} + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +} +} + +#include + +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#endif // BOOST_WINAPI_PIPES_HPP_INCLUDED_ diff --git a/boost/winapi/process.hpp b/boost/winapi/process.hpp new file mode 100644 index 0000000..9bcc3a6 --- /dev/null +++ b/boost/winapi/process.hpp @@ -0,0 +1,526 @@ +/* + * Copyright 2016 Klemens D. Morgenstern + * Copyright 2016, 2017 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_PROCESS_HPP_INCLUDED_ +#define BOOST_WINAPI_PROCESS_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +struct _PROCESS_INFORMATION; +#if !defined( BOOST_NO_ANSI_APIS ) +struct _STARTUPINFOA; +#endif +struct _STARTUPINFOW; +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM +struct _PROC_THREAD_ATTRIBUTE_LIST; +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP +#if !defined( BOOST_NO_ANSI_APIS ) +struct _STARTUPINFOEXA; +#endif +struct _STARTUPINFOEXW; +#endif // BOOST_WINAPI_PARTITION_DESKTOP + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if !defined(_WIN32_WCE) +// On Windows CE ExitProcess is a macro to call TerminateProcess +BOOST_WINAPI_IMPORT BOOST_NORETURN boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +ExitProcess(boost::winapi::UINT_ uExitCode); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC GetExitCodeProcess( + boost::winapi::HANDLE_ hProcess, + boost::winapi::LPDWORD_ lpExitCode); + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CreateProcessA( + boost::winapi::LPCSTR_ lpApplicationName, + boost::winapi::LPSTR_ lpCommandLine, + ::_SECURITY_ATTRIBUTES* lpProcessAttributes, + ::_SECURITY_ATTRIBUTES* lpThreadAttributes, + boost::winapi::INT_ bInheritHandles, + boost::winapi::DWORD_ dwCreationFlags, + boost::winapi::LPVOID_ lpEnvironment, + boost::winapi::LPCSTR_ lpCurrentDirectory, + ::_STARTUPINFOA* lpStartupInfo, + ::_PROCESS_INFORMATION* lpProcessInformation); +#endif + +#if defined(_WIN32_WCE) +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CreateProcessW( + boost::winapi::LPCWSTR_ lpApplicationName, + boost::winapi::LPCWSTR_ lpCommandLine, + ::_SECURITY_ATTRIBUTES* lpProcessAttributes, + ::_SECURITY_ATTRIBUTES* lpThreadAttributes, + boost::winapi::INT_ bInheritHandles, + boost::winapi::DWORD_ dwCreationFlags, + boost::winapi::LPVOID_ lpEnvironment, + boost::winapi::LPWSTR_ lpCurrentDirectory, + ::_STARTUPINFOW* lpStartupInfo, + ::_PROCESS_INFORMATION* lpProcessInformation); +#else +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CreateProcessW( + boost::winapi::LPCWSTR_ lpApplicationName, + boost::winapi::LPWSTR_ lpCommandLine, + ::_SECURITY_ATTRIBUTES* lpProcessAttributes, + ::_SECURITY_ATTRIBUTES* lpThreadAttributes, + boost::winapi::INT_ bInheritHandles, + boost::winapi::DWORD_ dwCreationFlags, + boost::winapi::LPVOID_ lpEnvironment, + boost::winapi::LPCWSTR_ lpCurrentDirectory, + ::_STARTUPINFOW* lpStartupInfo, + ::_PROCESS_INFORMATION* lpProcessInformation); +#endif + + +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC OpenProcess( + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::BOOL_ bInheritHandle, + boost::winapi::DWORD_ dwProcessId); + +#if defined(_WIN32_WCE) +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC TerminateProcess( + boost::winapi::HANDLE_ hProcess, + boost::winapi::DWORD_ uExitCode); +#else +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC TerminateProcess( + boost::winapi::HANDLE_ hProcess, + boost::winapi::UINT_ uExitCode); +#endif + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +} // extern "C" +#endif // defined BOOST_WINDOWS_H + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +BOOST_CONSTEXPR_OR_CONST DWORD_ DEBUG_PROCESS_ = DEBUG_PROCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ DEBUG_ONLY_THIS_PROCESS_ = DEBUG_ONLY_THIS_PROCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SUSPENDED_ = CREATE_SUSPENDED; +BOOST_CONSTEXPR_OR_CONST DWORD_ DETACHED_PROCESS_ = DETACHED_PROCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_CONSOLE_ = CREATE_NEW_CONSOLE; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_PROCESS_GROUP_ = CREATE_NEW_PROCESS_GROUP; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_UNICODE_ENVIRONMENT_ = CREATE_UNICODE_ENVIRONMENT; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SEPARATE_WOW_VDM_ = CREATE_SEPARATE_WOW_VDM; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SHARED_WOW_VDM_ = CREATE_SHARED_WOW_VDM; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_FORCEDOS_ = CREATE_FORCEDOS; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_BREAKAWAY_FROM_JOB_ = CREATE_BREAKAWAY_FROM_JOB; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_DEFAULT_ERROR_MODE_ = CREATE_DEFAULT_ERROR_MODE; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NO_WINDOW_ = CREATE_NO_WINDOW; + +// Undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_USER_ = PROFILE_USER; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_KERNEL_ = PROFILE_KERNEL; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_SERVER_ = PROFILE_SERVER; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_PROTECTED_PROCESS_ = CREATE_PROTECTED_PROCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ EXTENDED_STARTUPINFO_PRESENT_ = EXTENDED_STARTUPINFO_PRESENT; +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7 +BOOST_CONSTEXPR_OR_CONST DWORD_ INHERIT_PARENT_AFFINITY_ = INHERIT_PARENT_AFFINITY; +#endif + +// Only documented for Windows CE +#if defined(UNDER_CE) +BOOST_CONSTEXPR_OR_CONST DWORD_ INHERIT_CALLER_PRIORITY_ = INHERIT_CALLER_PRIORITY; +#endif + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP + +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESHOWWINDOW_ = STARTF_USESHOWWINDOW; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESIZE_ = STARTF_USESIZE; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEPOSITION_ = STARTF_USEPOSITION; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USECOUNTCHARS_ = STARTF_USECOUNTCHARS; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEFILLATTRIBUTE_ = STARTF_USEFILLATTRIBUTE; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_RUNFULLSCREEN_ = STARTF_RUNFULLSCREEN; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_FORCEONFEEDBACK_ = STARTF_FORCEONFEEDBACK; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_FORCEOFFFEEDBACK_ = STARTF_FORCEOFFFEEDBACK; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESTDHANDLES_ = STARTF_USESTDHANDLES; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEHOTKEY_ = STARTF_USEHOTKEY; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7 +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_TITLEISLINKNAME_ = STARTF_TITLEISLINKNAME; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_TITLEISAPPID_ = STARTF_TITLEISAPPID; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_PREVENTPINNING_ = STARTF_PREVENTPINNING; +#endif + +#endif // BOOST_WINAPI_PARTITION_DESKTOP + +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_TERMINATE_ = PROCESS_TERMINATE; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_CREATE_THREAD_ = PROCESS_CREATE_THREAD; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_SESSIONID_ = PROCESS_SET_SESSIONID; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_OPERATION_ = PROCESS_VM_OPERATION; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_READ_ = PROCESS_VM_READ; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_WRITE_ = PROCESS_VM_WRITE; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_DUP_HANDLE_ = PROCESS_DUP_HANDLE; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_CREATE_PROCESS_ = PROCESS_CREATE_PROCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_QUOTA_ = PROCESS_SET_QUOTA; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_INFORMATION_ = PROCESS_SET_INFORMATION; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_QUERY_INFORMATION_ = PROCESS_QUERY_INFORMATION; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SUSPEND_RESUME_ = PROCESS_SUSPEND_RESUME; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_ALL_ACCESS_ = PROCESS_ALL_ACCESS; + +#else // defined( BOOST_USE_WINDOWS_H ) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +BOOST_CONSTEXPR_OR_CONST DWORD_ DEBUG_PROCESS_ = 0x1; +BOOST_CONSTEXPR_OR_CONST DWORD_ DEBUG_ONLY_THIS_PROCESS_ = 0x2; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SUSPENDED_ = 0x4; +BOOST_CONSTEXPR_OR_CONST DWORD_ DETACHED_PROCESS_ = 0x8; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_CONSOLE_ = 0x10; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NEW_PROCESS_GROUP_ = 0x200; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_UNICODE_ENVIRONMENT_ = 0x400; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SEPARATE_WOW_VDM_ = 0x800; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_SHARED_WOW_VDM_ = 0x1000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_FORCEDOS_ = 0x2000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_BREAKAWAY_FROM_JOB_ = 0x1000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_DEFAULT_ERROR_MODE_ = 0x4000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_NO_WINDOW_ = 0x8000000; + +// Undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_USER_ = 0x10000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_KERNEL_ = 0x20000000; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROFILE_SERVER_ = 0x40000000; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_PROTECTED_PROCESS_ = 0x40000; +BOOST_CONSTEXPR_OR_CONST DWORD_ EXTENDED_STARTUPINFO_PRESENT_ = 0x80000; +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7 +BOOST_CONSTEXPR_OR_CONST DWORD_ INHERIT_PARENT_AFFINITY_ = 0x10000; +#endif + +// Only documented for Windows CE +#if defined(UNDER_CE) +BOOST_CONSTEXPR_OR_CONST DWORD_ INHERIT_CALLER_PRIORITY_ = 0x20000; +#endif + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP + +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESHOWWINDOW_ = 0x00000001; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESIZE_ = 0x00000002; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEPOSITION_ = 0x00000004; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USECOUNTCHARS_ = 0x00000008; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEFILLATTRIBUTE_ = 0x00000010; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_RUNFULLSCREEN_ = 0x00000020; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_FORCEONFEEDBACK_ = 0x00000040; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_FORCEOFFFEEDBACK_ = 0x00000080; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USESTDHANDLES_ = 0x00000100; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_USEHOTKEY_ = 0x00000200; + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN7 +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_TITLEISLINKNAME_ = 0x00000800; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_TITLEISAPPID_ = 0x00001000; +BOOST_CONSTEXPR_OR_CONST DWORD_ STARTF_PREVENTPINNING_ = 0x00002000; +#endif + +#endif // BOOST_WINAPI_PARTITION_DESKTOP + +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_TERMINATE_ = 0x0001; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_CREATE_THREAD_ = 0x0002; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_SESSIONID_ = 0x0004; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_OPERATION_ = 0x0008; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_READ_ = 0x0010; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_VM_WRITE_ = 0x0020; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_DUP_HANDLE_ = 0x0040; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_CREATE_PROCESS_ = 0x0080; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_QUOTA_ = 0x0100; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SET_INFORMATION_ = 0x0200; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_QUERY_INFORMATION_ = 0x0400; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_SUSPEND_RESUME_ = 0x0800; +BOOST_CONSTEXPR_OR_CONST DWORD_ PROCESS_ALL_ACCESS_ = (STANDARD_RIGHTS_REQUIRED_ | SYNCHRONIZE_ | +#if BOOST_USE_NTDDI_VERSION >= BOOST_WINAPI_NTDDI_WIN6 + 0xFFFF +#else + 0x0FFF +#endif +); + +#endif // defined( BOOST_USE_WINDOWS_H ) + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_PRESERVE_CODE_AUTHZ_LEVEL_ = CREATE_PRESERVE_CODE_AUTHZ_LEVEL; + +// Undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_IGNORE_SYSTEM_DEFAULT_ = CREATE_IGNORE_SYSTEM_DEFAULT; + +#else // defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_PRESERVE_CODE_AUTHZ_LEVEL_ = 0x2000000; + +// Undocumented +BOOST_CONSTEXPR_OR_CONST DWORD_ CREATE_IGNORE_SYSTEM_DEFAULT_ = 0x80000000; + +#endif // defined( BOOST_USE_WINDOWS_H ) && !defined( BOOST_WINAPI_IS_MINGW ) + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +typedef struct BOOST_MAY_ALIAS _PROCESS_INFORMATION { + HANDLE_ hProcess; + HANDLE_ hThread; + DWORD_ dwProcessId; + DWORD_ dwThreadId; +} PROCESS_INFORMATION_, *PPROCESS_INFORMATION_, *LPPROCESS_INFORMATION_; + +#if !defined(BOOST_NO_ANSI_APIS) +typedef struct BOOST_MAY_ALIAS _STARTUPINFOA { + DWORD_ cb; + LPSTR_ lpReserved; + LPSTR_ lpDesktop; + LPSTR_ lpTitle; + DWORD_ dwX; + DWORD_ dwY; + DWORD_ dwXSize; + DWORD_ dwYSize; + DWORD_ dwXCountChars; + DWORD_ dwYCountChars; + DWORD_ dwFillAttribute; + DWORD_ dwFlags; + WORD_ wShowWindow; + WORD_ cbReserved2; + LPBYTE_ lpReserved2; + HANDLE_ hStdInput; + HANDLE_ hStdOutput; + HANDLE_ hStdError; +} STARTUPINFOA_, *LPSTARTUPINFOA_; +#endif // !defined(BOOST_NO_ANSI_APIS) + +typedef struct BOOST_MAY_ALIAS _STARTUPINFOW { + DWORD_ cb; + LPWSTR_ lpReserved; + LPWSTR_ lpDesktop; + LPWSTR_ lpTitle; + DWORD_ dwX; + DWORD_ dwY; + DWORD_ dwXSize; + DWORD_ dwYSize; + DWORD_ dwXCountChars; + DWORD_ dwYCountChars; + DWORD_ dwFillAttribute; + DWORD_ dwFlags; + WORD_ wShowWindow; + WORD_ cbReserved2; + LPBYTE_ lpReserved2; + HANDLE_ hStdInput; + HANDLE_ hStdOutput; + HANDLE_ hStdError; +} STARTUPINFOW_, *LPSTARTUPINFOW_; + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM +typedef struct _PROC_THREAD_ATTRIBUTE_LIST PROC_THREAD_ATTRIBUTE_LIST_, *PPROC_THREAD_ATTRIBUTE_LIST_; +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP + +#if !defined(BOOST_NO_ANSI_APIS) +typedef struct BOOST_MAY_ALIAS _STARTUPINFOEXA { + STARTUPINFOA_ StartupInfo; + PPROC_THREAD_ATTRIBUTE_LIST_ lpAttributeList; +} STARTUPINFOEXA_, *LPSTARTUPINFOEXA_; +#endif // !defined(BOOST_NO_ANSI_APIS) + +typedef struct BOOST_MAY_ALIAS _STARTUPINFOEXW { + STARTUPINFOW_ StartupInfo; + PPROC_THREAD_ATTRIBUTE_LIST_ lpAttributeList; +} STARTUPINFOEXW_, *LPSTARTUPINFOEXW_; + +#endif // BOOST_WINAPI_PARTITION_DESKTOP + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +using ::TerminateProcess; +using ::OpenProcess; + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +using ::GetExitCodeProcess; +#if !defined(_WIN32_WCE) +using ::ExitProcess; +#endif + +BOOST_FORCEINLINE BOOST_NORETURN boost::winapi::VOID_ exit_process( + boost::winapi::UINT_ uExitCode) +{ +#if !defined(_WIN32_WCE) + ExitProcess(uExitCode); +#else + // ExitProcess macro in Windows CE and Windows Mobile SDKs actually does this + TerminateProcess(GetCurrentProcess(), (uExitCode)); +#endif +} + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE BOOL_ CreateProcessA( + LPCSTR_ lpApplicationName, + LPSTR_ lpCommandLine, + LPSECURITY_ATTRIBUTES_ lpProcessAttributes, + LPSECURITY_ATTRIBUTES_ lpThreadAttributes, + INT_ bInheritHandles, + DWORD_ dwCreationFlags, + LPVOID_ lpEnvironment, + LPCSTR_ lpCurrentDirectory, + LPSTARTUPINFOA_ lpStartupInfo, + LPPROCESS_INFORMATION_ lpProcessInformation) +{ + return ::CreateProcessA( + lpApplicationName, + lpCommandLine, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes), + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes), + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + reinterpret_cast< ::_STARTUPINFOA* >(lpStartupInfo), + reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation)); +} + +BOOST_FORCEINLINE BOOL_ create_process( + LPCSTR_ lpApplicationName, + LPSTR_ lpCommandLine, + LPSECURITY_ATTRIBUTES_ lpProcessAttributes, + LPSECURITY_ATTRIBUTES_ lpThreadAttributes, + INT_ bInheritHandles, + DWORD_ dwCreationFlags, + LPVOID_ lpEnvironment, + LPCSTR_ lpCurrentDirectory, + LPSTARTUPINFOA_ lpStartupInfo, + LPPROCESS_INFORMATION_ lpProcessInformation) +{ + return ::CreateProcessA( + lpApplicationName, + lpCommandLine, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes), + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes), + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + reinterpret_cast< ::_STARTUPINFOA* >(lpStartupInfo), + reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation)); +} +#endif + +BOOST_FORCEINLINE BOOL_ CreateProcessW( + LPCWSTR_ lpApplicationName, + LPWSTR_ lpCommandLine, + LPSECURITY_ATTRIBUTES_ lpProcessAttributes, + LPSECURITY_ATTRIBUTES_ lpThreadAttributes, + INT_ bInheritHandles, + DWORD_ dwCreationFlags, + LPVOID_ lpEnvironment, + LPCWSTR_ lpCurrentDirectory, + LPSTARTUPINFOW_ lpStartupInfo, + LPPROCESS_INFORMATION_ lpProcessInformation) +{ + return ::CreateProcessW( + lpApplicationName, + lpCommandLine, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes), + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes), + bInheritHandles, + dwCreationFlags, + lpEnvironment, +#if defined(_WIN32_WCE) + const_cast(lpCurrentDirectory), +#else + lpCurrentDirectory, +#endif + reinterpret_cast< ::_STARTUPINFOW* >(lpStartupInfo), + reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation)); +} + +BOOST_FORCEINLINE BOOL_ create_process( + LPCWSTR_ lpApplicationName, + LPWSTR_ lpCommandLine, + LPSECURITY_ATTRIBUTES_ lpProcessAttributes, + LPSECURITY_ATTRIBUTES_ lpThreadAttributes, + INT_ bInheritHandles, + DWORD_ dwCreationFlags, + LPVOID_ lpEnvironment, + LPCWSTR_ lpCurrentDirectory, + LPSTARTUPINFOW_ lpStartupInfo, + LPPROCESS_INFORMATION_ lpProcessInformation) +{ + return ::CreateProcessW( + lpApplicationName, + lpCommandLine, + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpProcessAttributes), + reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpThreadAttributes), + bInheritHandles, + dwCreationFlags, + lpEnvironment, +#if defined(_WIN32_WCE) + const_cast(lpCurrentDirectory), +#else + lpCurrentDirectory, +#endif + reinterpret_cast< ::_STARTUPINFOW* >(lpStartupInfo), + reinterpret_cast< ::_PROCESS_INFORMATION* >(lpProcessInformation)); +} + +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +} +} + +#include + +#endif // BOOST_WINAPI_PROCESS_HPP_INCLUDED_ diff --git a/boost/winapi/semaphore.hpp b/boost/winapi/semaphore.hpp new file mode 100644 index 0000000..0071f71 --- /dev/null +++ b/boost/winapi/semaphore.hpp @@ -0,0 +1,189 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_SEMAPHORE_HPP_INCLUDED_ +#define BOOST_WINAPI_SEMAPHORE_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +#if !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateSemaphoreA( + ::_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, + boost::winapi::LONG_ lInitialCount, + boost::winapi::LONG_ lMaximumCount, + boost::winapi::LPCSTR_ lpName); + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateSemaphoreExA( + ::_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, + boost::winapi::LONG_ lInitialCount, + boost::winapi::LONG_ lMaximumCount, + boost::winapi::LPCSTR_ lpName, + boost::winapi::DWORD_ dwFlags, + boost::winapi::DWORD_ dwDesiredAccess); +#endif + +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateSemaphoreW( + ::_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, + boost::winapi::LONG_ lInitialCount, + boost::winapi::LONG_ lMaximumCount, + boost::winapi::LPCWSTR_ lpName); + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +CreateSemaphoreExW( + ::_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, + boost::winapi::LONG_ lInitialCount, + boost::winapi::LONG_ lMaximumCount, + boost::winapi::LPCWSTR_ lpName, + boost::winapi::DWORD_ dwFlags, + boost::winapi::DWORD_ dwDesiredAccess); +#endif + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +ReleaseSemaphore( + boost::winapi::HANDLE_ hSemaphore, + boost::winapi::LONG_ lReleaseCount, + boost::winapi::LPLONG_ lpPreviousCount); + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +OpenSemaphoreA( + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::BOOL_ bInheritHandle, + boost::winapi::LPCSTR_ lpName); +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_WINAPI_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC +OpenSemaphoreW( + boost::winapi::DWORD_ dwDesiredAccess, + boost::winapi::BOOL_ bInheritHandle, + boost::winapi::LPCWSTR_ lpName); + +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +} // extern "C" +#endif // !defined( BOOST_USE_WINDOWS_H ) + +namespace boost { +namespace winapi { + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +using ::ReleaseSemaphore; + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ SEMAPHORE_ALL_ACCESS_ = SEMAPHORE_ALL_ACCESS; +BOOST_CONSTEXPR_OR_CONST DWORD_ SEMAPHORE_MODIFY_STATE_ = SEMAPHORE_MODIFY_STATE; + +#else // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ SEMAPHORE_ALL_ACCESS_ = 0x001F0003; +BOOST_CONSTEXPR_OR_CONST DWORD_ SEMAPHORE_MODIFY_STATE_ = 0x00000002; + +#endif // defined( BOOST_USE_WINDOWS_H ) + +// Undocumented and not present in Windows SDK. Enables NtQuerySemaphore. +// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FEvent%2FNtQueryEvent.html +BOOST_CONSTEXPR_OR_CONST DWORD_ SEMAPHORE_QUERY_STATE_ = 0x00000001; + +BOOST_CONSTEXPR_OR_CONST DWORD_ semaphore_all_access = SEMAPHORE_ALL_ACCESS_; +BOOST_CONSTEXPR_OR_CONST DWORD_ semaphore_modify_state = SEMAPHORE_MODIFY_STATE_; + + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE HANDLE_ CreateSemaphoreA(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCSTR_ lpName) +{ + return ::CreateSemaphoreA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSemaphoreAttributes), lInitialCount, lMaximumCount, lpName); +} + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_FORCEINLINE HANDLE_ CreateSemaphoreExA(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCSTR_ lpName, DWORD_ dwFlags, DWORD_ dwDesiredAccess) +{ + return ::CreateSemaphoreExA(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSemaphoreAttributes), lInitialCount, lMaximumCount, lpName, dwFlags, dwDesiredAccess); +} +#endif +#endif // !defined( BOOST_NO_ANSI_APIS ) + +BOOST_FORCEINLINE HANDLE_ CreateSemaphoreW(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCWSTR_ lpName) +{ + return ::CreateSemaphoreW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSemaphoreAttributes), lInitialCount, lMaximumCount, lpName); +} + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 +BOOST_FORCEINLINE HANDLE_ CreateSemaphoreExW(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCWSTR_ lpName, DWORD_ dwFlags, DWORD_ dwDesiredAccess) +{ + return ::CreateSemaphoreExW(reinterpret_cast< ::_SECURITY_ATTRIBUTES* >(lpSemaphoreAttributes), lInitialCount, lMaximumCount, lpName, dwFlags, dwDesiredAccess); +} +#endif + +#if !defined( BOOST_NO_ANSI_APIS ) +BOOST_FORCEINLINE HANDLE_ create_semaphore(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCSTR_ lpName) +{ + return winapi::CreateSemaphoreA(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); +} +#endif + +BOOST_FORCEINLINE HANDLE_ create_semaphore(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount, LPCWSTR_ lpName) +{ + return winapi::CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName); +} + +BOOST_FORCEINLINE HANDLE_ create_anonymous_semaphore(SECURITY_ATTRIBUTES_* lpSemaphoreAttributes, LONG_ lInitialCount, LONG_ lMaximumCount) +{ + return winapi::CreateSemaphoreW(lpSemaphoreAttributes, lInitialCount, lMaximumCount, 0); +} + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +#if BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +#if !defined( BOOST_NO_ANSI_APIS ) +using ::OpenSemaphoreA; + +BOOST_FORCEINLINE HANDLE_ open_semaphore(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCSTR_ lpName) +{ + return ::OpenSemaphoreA(dwDesiredAccess, bInheritHandle, lpName); +} +#endif // !defined( BOOST_NO_ANSI_APIS ) + +using ::OpenSemaphoreW; + +BOOST_FORCEINLINE HANDLE_ open_semaphore(DWORD_ dwDesiredAccess, BOOL_ bInheritHandle, LPCWSTR_ lpName) +{ + return ::OpenSemaphoreW(dwDesiredAccess, bInheritHandle, lpName); +} + +#endif // BOOST_WINAPI_PARTITION_DESKTOP_SYSTEM + +} +} + +#include + +#endif // BOOST_WINAPI_SEMAPHORE_HPP_INCLUDED_ diff --git a/boost/winapi/srw_lock.hpp b/boost/winapi/srw_lock.hpp new file mode 100644 index 0000000..d8a0e91 --- /dev/null +++ b/boost/winapi/srw_lock.hpp @@ -0,0 +1,116 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_SRW_LOCK_HPP_INCLUDED_ +#define BOOST_WINAPI_SRW_LOCK_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_WIN6 \ + || (defined(_MSC_VER) && _MSC_VER < 1600) +// Windows SDK 6.0A, which is used by MSVC 9, does not have TryAcquireSRWLock* neither in headers nor in .lib files, +// although the functions are present in later SDKs since Windows API version 6. +#define BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK +#endif + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#include +#include + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { +struct _RTL_SRWLOCK; + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +InitializeSRWLock(::_RTL_SRWLOCK* SRWLock); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +ReleaseSRWLockExclusive(::_RTL_SRWLOCK* SRWLock); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +ReleaseSRWLockShared(::_RTL_SRWLOCK* SRWLock); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +AcquireSRWLockExclusive(::_RTL_SRWLOCK* SRWLock); + +BOOST_WINAPI_IMPORT boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +AcquireSRWLockShared(::_RTL_SRWLOCK* SRWLock); + +#if !defined( BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK ) +BOOST_WINAPI_IMPORT boost::winapi::BOOLEAN_ BOOST_WINAPI_WINAPI_CC +TryAcquireSRWLockExclusive(::_RTL_SRWLOCK* SRWLock); + +BOOST_WINAPI_IMPORT boost::winapi::BOOLEAN_ BOOST_WINAPI_WINAPI_CC +TryAcquireSRWLockShared(::_RTL_SRWLOCK* SRWLock); +#endif +} // extern "C" +#endif + +namespace boost { +namespace winapi { + +typedef struct BOOST_MAY_ALIAS _RTL_SRWLOCK { + PVOID_ Ptr; +} SRWLOCK_, *PSRWLOCK_; + +#if defined( BOOST_USE_WINDOWS_H ) +#define BOOST_WINAPI_SRWLOCK_INIT SRWLOCK_INIT +#else +#define BOOST_WINAPI_SRWLOCK_INIT {0} +#endif + +BOOST_FORCEINLINE VOID_ InitializeSRWLock(PSRWLOCK_ SRWLock) +{ + ::InitializeSRWLock(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +BOOST_FORCEINLINE VOID_ ReleaseSRWLockExclusive(PSRWLOCK_ SRWLock) +{ + ::ReleaseSRWLockExclusive(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +BOOST_FORCEINLINE VOID_ ReleaseSRWLockShared(PSRWLOCK_ SRWLock) +{ + ::ReleaseSRWLockShared(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +BOOST_FORCEINLINE VOID_ AcquireSRWLockExclusive(PSRWLOCK_ SRWLock) +{ + ::AcquireSRWLockExclusive(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +BOOST_FORCEINLINE VOID_ AcquireSRWLockShared(PSRWLOCK_ SRWLock) +{ + ::AcquireSRWLockShared(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +#if !defined( BOOST_WINAPI_NO_TRY_ACQUIRE_SRWLOCK ) +BOOST_FORCEINLINE BOOLEAN_ TryAcquireSRWLockExclusive(PSRWLOCK_ SRWLock) +{ + return ::TryAcquireSRWLockExclusive(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} + +BOOST_FORCEINLINE BOOLEAN_ TryAcquireSRWLockShared(PSRWLOCK_ SRWLock) +{ + return ::TryAcquireSRWLockShared(reinterpret_cast< ::_RTL_SRWLOCK* >(SRWLock)); +} +#endif + +} +} + +#include + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 + +#endif // BOOST_WINAPI_SRW_LOCK_HPP_INCLUDED_ diff --git a/boost/winapi/thread.hpp b/boost/winapi/thread.hpp new file mode 100644 index 0000000..45ceb9c --- /dev/null +++ b/boost/winapi/thread.hpp @@ -0,0 +1,46 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_THREAD_HPP_INCLUDED_ +#define BOOST_WINAPI_THREAD_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM + +#include + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +SleepEx( + boost::winapi::DWORD_ dwMilliseconds, + boost::winapi::BOOL_ bAlertable); +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC Sleep(boost::winapi::DWORD_ dwMilliseconds); +BOOST_WINAPI_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC SwitchToThread(BOOST_WINAPI_DETAIL_VOID); +} // extern "C" +#endif + +namespace boost { +namespace winapi { +using ::SleepEx; +using ::Sleep; +using ::SwitchToThread; +} +} + +#include + +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM +#endif // BOOST_WINAPI_THREAD_HPP_INCLUDED_ diff --git a/boost/winapi/wait.hpp b/boost/winapi/wait.hpp new file mode 100644 index 0000000..23409b1 --- /dev/null +++ b/boost/winapi/wait.hpp @@ -0,0 +1,91 @@ +/* + * Copyright 2010 Vicente J. Botet Escriba + * Copyright 2015 Andrey Semashev + * Copyright 2017 James E. King, III + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_WAIT_HPP_INCLUDED_ +#define BOOST_WINAPI_WAIT_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined( BOOST_USE_WINDOWS_H ) +extern "C" { + +#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +WaitForSingleObjectEx( + boost::winapi::HANDLE_ hHandle, + boost::winapi::DWORD_ dwMilliseconds, + boost::winapi::BOOL_ bAlertable); +#endif + +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +SignalObjectAndWait( + boost::winapi::HANDLE_ hObjectToSignal, + boost::winapi::HANDLE_ hObjectToWaitOn, + boost::winapi::DWORD_ dwMilliseconds, + boost::winapi::BOOL_ bAlertable); +#endif +#endif + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +WaitForSingleObject( + boost::winapi::HANDLE_ hHandle, + boost::winapi::DWORD_ dwMilliseconds); + +BOOST_WINAPI_IMPORT_EXCEPT_WM boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +WaitForMultipleObjects( + boost::winapi::DWORD_ nCount, + boost::winapi::HANDLE_ const* lpHandles, + boost::winapi::BOOL_ bWaitAll, + boost::winapi::DWORD_ dwMilliseconds); + +BOOST_WINAPI_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC +WaitForMultipleObjectsEx( + boost::winapi::DWORD_ nCount, + boost::winapi::HANDLE_ const* lpHandles, + boost::winapi::BOOL_ bWaitAll, + boost::winapi::DWORD_ dwMilliseconds, + boost::winapi::BOOL_ bAlertable); +#endif // BOOST_WINAPI_PARTITION_APP_SYSTEM + +} // extern "C" +#endif + +namespace boost { +namespace winapi { + +#if BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM +using ::WaitForSingleObjectEx; +#endif +#if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_NT4 +using ::SignalObjectAndWait; +#endif +#endif + +#if BOOST_WINAPI_PARTITION_APP_SYSTEM +using ::WaitForMultipleObjects; +using ::WaitForMultipleObjectsEx; +using ::WaitForSingleObject; +#endif + +} +} + +#include + +#endif // BOOST_WINAPI_WAIT_HPP_INCLUDED_ diff --git a/boost/winapi/wait_constants.hpp b/boost/winapi/wait_constants.hpp new file mode 100644 index 0000000..867b74f --- /dev/null +++ b/boost/winapi/wait_constants.hpp @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_WAIT_CONSTANTS_HPP_INCLUDED_ +#define BOOST_WINAPI_WAIT_CONSTANTS_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace winapi { + +#if defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ INFINITE_ = INFINITE; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_ABANDONED_ = WAIT_ABANDONED; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_OBJECT_0_ = WAIT_OBJECT_0; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_TIMEOUT_ = WAIT_TIMEOUT; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_FAILED_ = WAIT_FAILED; + +#else // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ INFINITE_ = (DWORD_)0xFFFFFFFF; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_ABANDONED_ = 0x00000080L; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_OBJECT_0_ = 0x00000000L; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_TIMEOUT_ = 0x00000102L; +BOOST_CONSTEXPR_OR_CONST DWORD_ WAIT_FAILED_ = (DWORD_)0xFFFFFFFF; + +#endif // defined( BOOST_USE_WINDOWS_H ) + +BOOST_CONSTEXPR_OR_CONST DWORD_ infinite = INFINITE_; +BOOST_CONSTEXPR_OR_CONST DWORD_ wait_abandoned = WAIT_ABANDONED_; +BOOST_CONSTEXPR_OR_CONST DWORD_ wait_object_0 = WAIT_OBJECT_0_; +BOOST_CONSTEXPR_OR_CONST DWORD_ wait_timeout = WAIT_TIMEOUT_; +BOOST_CONSTEXPR_OR_CONST DWORD_ wait_failed = WAIT_FAILED_; + +BOOST_CONSTEXPR_OR_CONST DWORD_ max_non_infinite_wait = (DWORD_)0xFFFFFFFE; + +} +} + +#include + +#endif // BOOST_WINAPI_WAIT_CONSTANTS_HPP_INCLUDED_ diff --git a/boost/winapi/wait_on_address.hpp b/boost/winapi/wait_on_address.hpp new file mode 100644 index 0000000..4558f39 --- /dev/null +++ b/boost/winapi/wait_on_address.hpp @@ -0,0 +1,56 @@ +/* + * Copyright 2020 Andrey Semashev + * + * Distributed under the Boost Software License, Version 1.0. + * See http://www.boost.org/LICENSE_1_0.txt + */ + +#ifndef BOOST_WINAPI_WAIT_ON_ADDRESS_HPP_INCLUDED_ +#define BOOST_WINAPI_WAIT_ON_ADDRESS_HPP_INCLUDED_ + +#include + +#if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM) + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_USE_WINDOWS_H) +extern "C" { + +// Note: These functions are not dllimport +boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC +WaitOnAddress( + volatile boost::winapi::VOID_* addr, + boost::winapi::PVOID_ compare_addr, + boost::winapi::SIZE_T_ size, + boost::winapi::DWORD_ timeout_ms); + +boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +WakeByAddressSingle(boost::winapi::PVOID_ addr); + +boost::winapi::VOID_ BOOST_WINAPI_WINAPI_CC +WakeByAddressAll(boost::winapi::PVOID_ addr); + +} // extern "C" +#endif // !defined(BOOST_USE_WINDOWS_H) + +namespace boost { +namespace winapi { + +using ::WaitOnAddress; +using ::WakeByAddressSingle; +using ::WakeByAddressAll; + +} +} + +#include + +#endif // BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN8 && (BOOST_WINAPI_PARTITION_APP || BOOST_WINAPI_PARTITION_SYSTEM) + +#endif // BOOST_WINAPI_WAIT_ON_ADDRESS_HPP_INCLUDED_ diff --git a/build.cmd b/build.cmd index 3974d6b..a7ec577 100644 --- a/build.cmd +++ b/build.cmd @@ -5,17 +5,14 @@ bcp ^ boost/container/small_vector.hpp ^ boost/container/static_vector.hpp ^ boost/crc.hpp ^ - boost/date_time/posix_time/posix_time.hpp ^ boost/icl/interval_map.hpp ^ boost/locale/encoding_utf.hpp ^ boost/optional.hpp ^ - boost/range/algorithm/ ^ - boost/range/algorithm_ext/ ^ - boost/smart_ptr/intrusive_ptr.hpp ^ + boost/algorithm/string/replace.hpp ^ boost/system/error_code.hpp ^ boost/system/system_error.hpp ^ + boost/process/async_pipe.hpp ^ boost/stacktrace.hpp ^ - boost/variant/ ^ boost/archive/binary_iarchive.hpp ^ boost/archive/binary_oarchive.hpp ^ boost/serialization/array.hpp ^ diff --git a/libs/filesystem/build/Jamfile.v2 b/libs/filesystem/build/Jamfile.v2 new file mode 100644 index 0000000..d2fd77c --- /dev/null +++ b/libs/filesystem/build/Jamfile.v2 @@ -0,0 +1,200 @@ +# Boost Filesystem Library Build Jamfile + +# (C) Copyright Beman Dawes 2002-2006 +# (C) Copyright Andrey Semashev 2020, 2021 +# Distributed under the Boost Software License, Version 1.0. +# See www.boost.org/LICENSE_1_0.txt + +# See library home page at http://www.boost.org/libs/filesystem + +import project ; +import configure ; + +lib bcrypt ; +lib advapi32 ; +lib coredll ; +explicit bcrypt advapi32 coredll ; + +# The rule checks if a config macro is defined in the command line or build properties +rule has-config-flag ( flag : properties * ) +{ + if ( "$(flag)" in $(properties) || "$(flag)=1" in $(properties) ) + { + return 1 ; + } + else + { + return ; + } +} + +# The rule checks we're building for Windows and selects crypto API to be used +rule select-windows-crypto-api ( properties * ) +{ + local result ; + + if windows in $(properties) || cygwin in $(properties) + { + if ! [ has-config-flag BOOST_FILESYSTEM_DISABLE_BCRYPT : $(properties) ] && + [ configure.builds ../config//has_bcrypt : $(properties) : "has BCrypt API" ] + { + result = BOOST_FILESYSTEM_HAS_BCRYPT bcrypt ; + } + else + { + result = BOOST_FILESYSTEM_HAS_WINCRYPT ; + if [ configure.builds ../config//is_windows_ce : $(properties) : "is Windows CE" ] + { + result += coredll ; + } + else + { + result += advapi32 ; + } + } + } + + #ECHO Result: $(result) ; + return $(result) ; +} + +# The rule checks if statx syscall is supported +rule check-statx ( properties * ) +{ + local result ; + + if ! [ has-config-flag BOOST_FILESYSTEM_DISABLE_STATX : $(properties) ] + { + if [ configure.builds ../config//has_statx : $(properties) : "has statx" ] + { + result = BOOST_FILESYSTEM_HAS_STATX ; + } + else if [ configure.builds ../config//has_statx_syscall : $(properties) : "has statx syscall" ] + { + result = BOOST_FILESYSTEM_HAS_STATX_SYSCALL ; + } + } + + #ECHO Result: $(result) ; + return $(result) ; +} + +# The rule checks if std::atomic_ref is supported +rule check-cxx20-atomic-ref ( properties * ) +{ + local result ; + + if ! single in $(properties) + { + if ! [ configure.builds ../config//has_cxx20_atomic_ref : $(properties) : "has std::atomic_ref" ] + { + result = BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF ; + result += /boost/atomic//boost_atomic ; + } + } + else + { + result = BOOST_FILESYSTEM_SINGLE_THREADED ; + } + + #ECHO Result: $(result) ; + return $(result) ; +} + +# The rule checks if the linker supports requiring no unresolved symbols +rule check-linkflag-no-undefined ( properties * ) +{ + local result ; + + if shared in $(properties) + { + if [ configure.builds ../config//has_linkflag_no_undefined : $(properties) : "has -Wl,--no-undefined" ] + { + result = "-Wl,--no-undefined" ; + } + else if [ configure.builds ../config//has_linkflag_undefined_error : $(properties) : "has -Wl,-undefined,error" ] + { + result = "-Wl,-undefined,error" ; + } + } + + #ECHO Result: $(result) ; + return $(result) ; +} + +project boost/filesystem + : requirements + hpux,gcc:_INCLUDE_STDC__SOURCE_199901 + [ check-target-builds ../config//has_attribute_init_priority "has init_priority attribute" : BOOST_FILESYSTEM_HAS_INIT_PRIORITY ] + [ check-target-builds ../config//has_stat_st_mtim "has stat::st_blksize" : BOOST_FILESYSTEM_HAS_STAT_ST_BLKSIZE ] + [ check-target-builds ../config//has_stat_st_mtim "has stat::st_mtim" : BOOST_FILESYSTEM_HAS_STAT_ST_MTIM ] + [ check-target-builds ../config//has_stat_st_mtimensec "has stat::st_mtimensec" : BOOST_FILESYSTEM_HAS_STAT_ST_MTIMENSEC ] + [ check-target-builds ../config//has_stat_st_mtimespec "has stat::st_mtimespec" : BOOST_FILESYSTEM_HAS_STAT_ST_MTIMESPEC ] + [ check-target-builds ../config//has_stat_st_birthtim "has stat::st_birthtim" : BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIM ] + [ check-target-builds ../config//has_stat_st_birthtimensec "has stat::st_birthtimensec" : BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIMENSEC ] + [ check-target-builds ../config//has_stat_st_birthtimespec "has stat::st_birthtimespec" : BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIMESPEC ] + [ check-target-builds ../config//has_fdopendir_nofollow "has fdopendir(O_NOFOLLOW)" : BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW ] + [ check-target-builds ../config//has_dirent_d_type "has dirent::d_type" : BOOST_FILESYSTEM_HAS_DIRENT_D_TYPE ] + [ check-target-builds ../config//has_posix_at_apis "has POSIX *at APIs" : BOOST_FILESYSTEM_HAS_POSIX_AT_APIS ] + @check-statx + @select-windows-crypto-api + @check-cxx20-atomic-ref + # Make sure no undefined references are left from the library + @check-linkflag-no-undefined + windows:_SCL_SECURE_NO_WARNINGS + windows:_SCL_SECURE_NO_DEPRECATE + windows:_CRT_SECURE_NO_WARNINGS + windows:_CRT_SECURE_NO_DEPRECATE + windows:BOOST_USE_WINDOWS_H + windows:WIN32_LEAN_AND_MEAN + windows:NOMINMAX + cygwin:BOOST_USE_WINDOWS_H + cygwin:WIN32_LEAN_AND_MEAN + cygwin:NOMINMAX + + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105329 + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105651 + gcc-12:"-Wno-restrict" + + : source-location ../src + : usage-requirements # pass these requirement to dependents (i.e. users) + shared:BOOST_FILESYSTEM_DYN_LINK=1 + static:BOOST_FILESYSTEM_STATIC_LINK=1 + ; + +SOURCES = + codecvt_error_category + exception + directory + operations + path + path_traits + portability + unique_path + utf8_codecvt_facet + ; + +rule select-platform-specific-sources ( properties * ) +{ + local result ; + + if windows in $(properties) || cygwin in $(properties) + { + result += windows_file_codecvt.cpp ; + } + + return $(result) ; +} + +lib boost_filesystem + : $(SOURCES).cpp + : BOOST_FILESYSTEM_SOURCE + @select-platform-specific-sources + ../src + shared:BOOST_FILESYSTEM_DYN_LINK=1 + static:BOOST_FILESYSTEM_STATIC_LINK=1 + : + : + ; + +boost-install boost_filesystem ; diff --git a/libs/filesystem/config/Jamfile.v2 b/libs/filesystem/config/Jamfile.v2 new file mode 100644 index 0000000..1b36276 --- /dev/null +++ b/libs/filesystem/config/Jamfile.v2 @@ -0,0 +1,48 @@ +# +# Copyright Andrey Semashev 2020 - 2021. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# + +obj has_attribute_init_priority : has_attribute_init_priority.cpp : ../src ; +explicit has_attribute_init_priority ; +obj has_cxx20_atomic_ref : has_cxx20_atomic_ref.cpp : ../src ; +explicit has_cxx20_atomic_ref ; +obj has_stat_st_blksize : has_stat_st_blksize.cpp : ../src ; +explicit has_stat_st_blksize ; +obj has_stat_st_mtim : has_stat_st_mtim.cpp : ../src ; +explicit has_stat_st_mtim ; +obj has_stat_st_mtimensec : has_stat_st_mtimensec.cpp : ../src ; +explicit has_stat_st_mtimensec ; +obj has_stat_st_mtimespec : has_stat_st_mtimespec.cpp : ../src ; +explicit has_stat_st_mtimespec ; +obj has_statx : has_statx.cpp : ../src ; +explicit has_statx ; +obj has_statx_syscall : has_statx_syscall.cpp : ../src ; +explicit has_statx_syscall ; +obj has_stat_st_birthtim : has_stat_st_birthtim.cpp : ../src ; +explicit has_stat_st_birthtim ; +obj has_stat_st_birthtimensec : has_stat_st_birthtimensec.cpp : ../src ; +explicit has_stat_st_birthtimensec ; +obj has_stat_st_birthtimespec : has_stat_st_birthtimespec.cpp : ../src ; +explicit has_stat_st_birthtimespec ; +obj has_fdopendir_nofollow : has_fdopendir_nofollow.cpp : ../src ; +explicit has_fdopendir_nofollow ; +obj has_dirent_d_type : has_dirent_d_type.cpp : ../src ; +explicit has_dirent_d_type ; +obj has_posix_at_apis : has_posix_at_apis.cpp : ../src ; +explicit has_posix_at_apis ; + +lib bcrypt ; +explicit bcrypt ; + +exe has_bcrypt : has_bcrypt.cpp : ../src bcrypt ; +explicit has_bcrypt ; +obj is_windows_ce : is_windows_ce.cpp ; +explicit is_windows_ce ; + +lib has_linkflag_no_undefined : has_linkflag_no_undefined.cpp : shared "-Wl,--no-undefined" ; +explicit has_linkflag_no_undefined ; +lib has_linkflag_undefined_error : has_linkflag_no_undefined.cpp : shared "-Wl,-undefined,error" ; +explicit has_linkflag_undefined_error ; diff --git a/libs/filesystem/config/has_attribute_init_priority.cpp b/libs/filesystem/config/has_attribute_init_priority.cpp new file mode 100644 index 0000000..87d3eba --- /dev/null +++ b/libs/filesystem/config/has_attribute_init_priority.cpp @@ -0,0 +1,20 @@ +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +struct global_class +{ + global_class() {} + ~global_class() {} +}; + +__attribute__ ((init_priority(32767))) +global_class g_object; + +int main() +{ + return 0; +} diff --git a/libs/filesystem/config/has_bcrypt.cpp b/libs/filesystem/config/has_bcrypt.cpp new file mode 100644 index 0000000..855d16e --- /dev/null +++ b/libs/filesystem/config/has_bcrypt.cpp @@ -0,0 +1,34 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +// Include platform_config.hpp first so that windows.h is guaranteed to be not included +#include "platform_config.hpp" + +#include +#include +#if !BOOST_OS_WINDOWS && !BOOST_OS_CYGWIN +#error "This config test is for Windows only" +#endif + +#include +#include +#if !(BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 && BOOST_WINAPI_PARTITION_APP_SYSTEM) +#error "No BCrypt API" +#endif + +#include +#include +#include + +int main() +{ + unsigned char buf[16] = {}; + boost::winapi::BCRYPT_ALG_HANDLE_ handle; + boost::winapi::NTSTATUS_ status = boost::winapi::BCryptOpenAlgorithmProvider(&handle, boost::winapi::BCRYPT_RNG_ALGORITHM_, NULL, 0); + status = boost::winapi::BCryptGenRandom(handle, reinterpret_cast< boost::winapi::PUCHAR_ >(static_cast< unsigned char* >(buf)), static_cast< boost::winapi::ULONG_ >(sizeof(buf)), 0); + boost::winapi::BCryptCloseAlgorithmProvider(handle, 0); +} diff --git a/libs/filesystem/config/has_cxx20_atomic_ref.cpp b/libs/filesystem/config/has_cxx20_atomic_ref.cpp new file mode 100644 index 0000000..1fb407f --- /dev/null +++ b/libs/filesystem/config/has_cxx20_atomic_ref.cpp @@ -0,0 +1,19 @@ +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include + +typedef void func_t(); + +int main() +{ + func_t* func = 0; + std::atomic_ref< func_t* > ref(func); + ref.load(std::memory_order_relaxed); + ref.store((func_t*)0, std::memory_order_relaxed); + return 0; +} diff --git a/libs/filesystem/config/has_dirent_d_type.cpp b/libs/filesystem/config/has_dirent_d_type.cpp new file mode 100644 index 0000000..d93cbfd --- /dev/null +++ b/libs/filesystem/config/has_dirent_d_type.cpp @@ -0,0 +1,39 @@ +// Copyright 2023 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include + +int main() +{ + DIR* dir = opendir("."); + dirent* ent = readdir(dir); + switch (ent->d_type) + { + case DT_REG: + break; + case DT_DIR: + break; + case DT_LNK: + break; + case DT_SOCK: + break; + case DT_FIFO: + break; + case DT_BLK: + break; + case DT_CHR: + break; + case DT_UNKNOWN: + break; + default: + break; + } + return 0; +} diff --git a/libs/filesystem/config/has_fdopendir_nofollow.cpp b/libs/filesystem/config/has_fdopendir_nofollow.cpp new file mode 100644 index 0000000..009a730 --- /dev/null +++ b/libs/filesystem/config/has_fdopendir_nofollow.cpp @@ -0,0 +1,20 @@ +// Copyright 2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include +#include + +int main() +{ + int fd = open(".", O_DIRECTORY | O_RDONLY | O_NOFOLLOW); + DIR* dir = fdopendir(fd); + return dir != 0; +} diff --git a/libs/filesystem/config/has_linkflag_no_undefined.cpp b/libs/filesystem/config/has_linkflag_no_undefined.cpp new file mode 100644 index 0000000..ae8f940 --- /dev/null +++ b/libs/filesystem/config/has_linkflag_no_undefined.cpp @@ -0,0 +1,27 @@ +// Copyright 2023 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#if defined(_MSC_VER) +// MSVC's link.exe does not support -Wl,... flags, but doesn't fail the linking. +// The linker may be used by different compilers, not only MSVC. +// Luckily, those compilers all pretend to be MSVC. +#error "MSVC and compatible compilers don't support -Wl,... flags" +#endif + +#if defined(__OpenBSD__) +// On OpenBSD, shared libraries are not linked to libc, as there are multiple +// libc versions installed, and loading multiple different versions into the +// process is considered dangerous. Only the main executable is linked against +// one of them, which will be used by all shared libraries loaded into the +// process. This renders -Wl,--no-undefined unusable for shared libraries. +#error "-Wl,--no-undefined is broken for shared libraries on OpenBSD" +#endif + +int main() +{ + return 0; +} diff --git a/libs/filesystem/config/has_posix_at_apis.cpp b/libs/filesystem/config/has_posix_at_apis.cpp new file mode 100644 index 0000000..094b629 --- /dev/null +++ b/libs/filesystem/config/has_posix_at_apis.cpp @@ -0,0 +1,41 @@ +// Copyright 2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include +#include +#include + +int main() +{ + int fd1 = openat(AT_FDCWD, "foo", O_DIRECTORY | O_RDONLY); + int fd2 = openat(fd1, "bar", O_DIRECTORY | O_RDONLY); + int res = unlinkat(fd2, "zoo", 0); + res |= unlinkat(fd1, "bar", AT_REMOVEDIR); + res |= renameat(AT_FDCWD, "x", fd1, "y"); + + struct stat st; + res |= fstatat(fd1, "y", &st, AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW); + + res |= linkat(fd1, "y", fd1, "z", 0); + res |= symlinkat("foo/z", fd1, "sz"); + + char buf[128u]; + res |= readlinkat(fd1, "sz", buf, sizeof(buf)); + + res |= mkdirat(fd1, "dir", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + + res |= fchmodat(fd1, "x", S_IRUSR | S_IWUSR, 0); + + struct timespec times[2] = {}; + res |= utimensat(fd1, "x", times, AT_SYMLINK_NOFOLLOW); + + return res != 0; +} diff --git a/libs/filesystem/config/has_stat_st_birthtim.cpp b/libs/filesystem/config/has_stat_st_birthtim.cpp new file mode 100644 index 0000000..3564391 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_birthtim.cpp @@ -0,0 +1,19 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_birthtim.tv_sec = 1; + st.st_birthtim.tv_nsec = 10; +} diff --git a/libs/filesystem/config/has_stat_st_birthtimensec.cpp b/libs/filesystem/config/has_stat_st_birthtimensec.cpp new file mode 100644 index 0000000..0a20cc0 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_birthtimensec.cpp @@ -0,0 +1,19 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_birthtime = 1; + st.st_birthtimensec = 10; +} diff --git a/libs/filesystem/config/has_stat_st_birthtimespec.cpp b/libs/filesystem/config/has_stat_st_birthtimespec.cpp new file mode 100644 index 0000000..175b293 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_birthtimespec.cpp @@ -0,0 +1,19 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_birthtimespec.tv_sec = 1; + st.st_birthtimespec.tv_nsec = 10; +} diff --git a/libs/filesystem/config/has_stat_st_blksize.cpp b/libs/filesystem/config/has_stat_st_blksize.cpp new file mode 100644 index 0000000..eafed7b --- /dev/null +++ b/libs/filesystem/config/has_stat_st_blksize.cpp @@ -0,0 +1,18 @@ +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_blksize = 10; +} diff --git a/libs/filesystem/config/has_stat_st_mtim.cpp b/libs/filesystem/config/has_stat_st_mtim.cpp new file mode 100644 index 0000000..6d024d1 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_mtim.cpp @@ -0,0 +1,18 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_mtim.tv_nsec = 10; +} diff --git a/libs/filesystem/config/has_stat_st_mtimensec.cpp b/libs/filesystem/config/has_stat_st_mtimensec.cpp new file mode 100644 index 0000000..36f6117 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_mtimensec.cpp @@ -0,0 +1,18 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_mtimensec = 10; +} diff --git a/libs/filesystem/config/has_stat_st_mtimespec.cpp b/libs/filesystem/config/has_stat_st_mtimespec.cpp new file mode 100644 index 0000000..02373f3 --- /dev/null +++ b/libs/filesystem/config/has_stat_st_mtimespec.cpp @@ -0,0 +1,18 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include + +int main() +{ + struct stat st; + st.st_mtimespec.tv_nsec = 10; +} diff --git a/libs/filesystem/config/has_statx.cpp b/libs/filesystem/config/has_statx.cpp new file mode 100644 index 0000000..d2ea017 --- /dev/null +++ b/libs/filesystem/config/has_statx.cpp @@ -0,0 +1,21 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include +#include + +int main() +{ + struct statx st; + int res = statx(AT_FDCWD, ".", AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_BTIME, &st); + st.stx_btime.tv_sec = 1; + st.stx_btime.tv_nsec = 10; +} diff --git a/libs/filesystem/config/has_statx_syscall.cpp b/libs/filesystem/config/has_statx_syscall.cpp new file mode 100644 index 0000000..571fe14 --- /dev/null +++ b/libs/filesystem/config/has_statx_syscall.cpp @@ -0,0 +1,35 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include + +// Note: Include other libc headers for stat() as well to ensure there is no conflict between +// Linux kernel headers and libc headers. +#include +#include +#include +#include + +#if defined(__ANDROID__) && (__ANDROID_API__ < 30) +// Even though statx syscall number is defined, it is blacklisted by seccomp in runtime until Android 11 +#error "statx syscall is not supported until Android 11" +#endif + +#if !defined(__NR_statx) +#error "No statx syscall" +#endif + +int main() +{ + struct statx st; + int res = syscall(__NR_statx, AT_FDCWD, ".", AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_BTIME, &st); + st.stx_btime.tv_sec = 1; + st.stx_btime.tv_nsec = 10; +} diff --git a/libs/filesystem/config/is_windows_ce.cpp b/libs/filesystem/config/is_windows_ce.cpp new file mode 100644 index 0000000..8681670 --- /dev/null +++ b/libs/filesystem/config/is_windows_ce.cpp @@ -0,0 +1,14 @@ +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#if !defined(_WIN32_WCE) +#error "This is not Windows CE" +#endif + +int main() +{ +} diff --git a/libs/filesystem/src/atomic_ref.hpp b/libs/filesystem/src/atomic_ref.hpp new file mode 100644 index 0000000..6e8208d --- /dev/null +++ b/libs/filesystem/src/atomic_ref.hpp @@ -0,0 +1,32 @@ +// atomic.hpp ------------------------------------------------------------------------// + +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_ATOMIC_REF_HPP_ +#define BOOST_FILESYSTEM_SRC_ATOMIC_REF_HPP_ + +#include + +#if !defined(BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF) + +#include + +namespace atomic_ns = std; + +#else // !defined(BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF) + +#include +#include + +namespace atomic_ns = boost; + +#endif // !defined(BOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF) + +#endif // BOOST_FILESYSTEM_SRC_ATOMIC_REF_HPP_ diff --git a/libs/filesystem/src/atomic_tools.hpp b/libs/filesystem/src/atomic_tools.hpp new file mode 100644 index 0000000..a60e5d3 --- /dev/null +++ b/libs/filesystem/src/atomic_tools.hpp @@ -0,0 +1,69 @@ +// atomic_tools.hpp ------------------------------------------------------------------// + +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_ATOMIC_TOOLS_HPP_ +#define BOOST_FILESYSTEM_SRC_ATOMIC_TOOLS_HPP_ + +#include + +#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + +#include "atomic_ref.hpp" + +namespace boost { +namespace filesystem { +namespace detail { + +//! Atomically loads the value +template< typename T > +BOOST_FORCEINLINE T atomic_load_relaxed(T& a) +{ + return atomic_ns::atomic_ref< T >(a).load(atomic_ns::memory_order_relaxed); +} + +//! Atomically stores the value +template< typename T > +BOOST_FORCEINLINE void atomic_store_relaxed(T& a, T val) +{ + atomic_ns::atomic_ref< T >(a).store(val, atomic_ns::memory_order_relaxed); +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + +namespace boost { +namespace filesystem { +namespace detail { + +//! Atomically loads the value +template< typename T > +BOOST_FORCEINLINE T atomic_load_relaxed(T const& a) +{ + return a; +} + +//! Atomically stores the value +template< typename T > +BOOST_FORCEINLINE void atomic_store_relaxed(T& a, T val) +{ + a = val; +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + +#endif // BOOST_FILESYSTEM_SRC_ATOMIC_TOOLS_HPP_ diff --git a/libs/filesystem/src/codecvt_error_category.cpp b/libs/filesystem/src/codecvt_error_category.cpp new file mode 100644 index 0000000..a8d2a42 --- /dev/null +++ b/libs/filesystem/src/codecvt_error_category.cpp @@ -0,0 +1,120 @@ +// codecvt_error_category implementation file ----------------------------------------// + +// Copyright 2009 Beman Dawes +// Copyright 2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt) + +// Library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include + +#include +#include +#include +#include +#include + +#include "private_config.hpp" + +#include // must be the last #include + +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { + +namespace { + +#if (defined(BOOST_GCC) && BOOST_GCC >= 40600) || defined(BOOST_CLANG) +#pragma GCC diagnostic push +// '(anonymous namespace)::codecvt_error_cat' has virtual functions but non-virtual destructor +// This is not a problem as instances of codecvt_error_cat are never destroyed through a pointer to base. +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + +class codecvt_error_cat BOOST_FINAL : + public boost::system::error_category +{ +public: + // clang up to version 3.8 requires a user-defined default constructor in order to be able to declare a static constant of the error category. + BOOST_SYSTEM_CONSTEXPR codecvt_error_cat() BOOST_NOEXCEPT {} + const char* name() const BOOST_NOEXCEPT BOOST_OVERRIDE; + std::string message(int ev) const BOOST_OVERRIDE; +}; + +const char* codecvt_error_cat::name() const BOOST_NOEXCEPT +{ + return "codecvt"; +} + +std::string codecvt_error_cat::message(int ev) const +{ + std::string str; + switch (ev) + { + case std::codecvt_base::ok: + str = "ok"; + break; + case std::codecvt_base::partial: + str = "partial"; + break; + case std::codecvt_base::error: + str = "error"; + break; + case std::codecvt_base::noconv: + str = "noconv"; + break; + default: + str = "unknown error"; + break; + } + return str; +} + +#if (defined(BOOST_GCC) && BOOST_GCC >= 40600) || defined(BOOST_CLANG) +#pragma GCC diagnostic pop +#endif + +} // unnamed namespace + +BOOST_FILESYSTEM_DECL boost::system::error_category const& codecvt_error_category() BOOST_NOEXCEPT +{ + static +#if defined(BOOST_SYSTEM_HAS_CONSTEXPR) + constexpr +#else + const +#endif + codecvt_error_cat codecvt_error_cat_const; + return codecvt_error_cat_const; +} + +// Try to initialize the error category instance as early as possible to make sure it is +// available during global deinitialization stage. For MSVC, codecvt_error_category() will +// be called early by MSVC-specific initialization routine in path.cpp. +#if !defined(BOOST_SYSTEM_HAS_CONSTEXPR) && !defined(_MSC_VER) + +namespace { + +struct codecvt_error_category_initializer +{ + codecvt_error_category_initializer() { boost::filesystem::codecvt_error_category(); } +}; + +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +const codecvt_error_category_initializer g_codecvt_error_category_initializer; + +} // namespace + +#endif // !defined(BOOST_SYSTEM_HAS_CONSTEXPR) && !defined(_MSC_VER) + +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/directory.cpp b/libs/filesystem/src/directory.cpp new file mode 100644 index 0000000..f769f8f --- /dev/null +++ b/libs/filesystem/src/directory.cpp @@ -0,0 +1,1510 @@ +// directory.cpp --------------------------------------------------------------------// + +// Copyright 2002-2009, 2014 Beman Dawes +// Copyright 2001 Dietmar Kuehl +// Copyright 2019, 2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include // std::malloc, std::free +#include // std::nothrow, std::bad_alloc +#include +#include +#include // std::move +#include +#include +#include + +#ifdef BOOST_POSIX_API + +#include +#include +#include +#include +#include + +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS >= 0) && defined(_SC_THREAD_SAFE_FUNCTIONS) && \ + !defined(__CYGWIN__) && \ + !(defined(linux) || defined(__linux) || defined(__linux__)) && \ + !defined(__ANDROID__) && \ + (!defined(__hpux) || defined(_REENTRANT)) && \ + (!defined(_AIX) || defined(__THREAD_SAFE)) && \ + !defined(__wasm) +#define BOOST_FILESYSTEM_USE_READDIR_R +#endif + +// At least Mac OS X 10.6 and older doesn't support O_CLOEXEC +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#define BOOST_FILESYSTEM_NO_O_CLOEXEC +#endif + +#include "posix_tools.hpp" + +#else // BOOST_WINDOWS_API + +#include +#include +#include // NTSTATUS_ + +#include "windows_tools.hpp" + +#endif // BOOST_WINDOWS_API + +#include "atomic_tools.hpp" +#include "error_handling.hpp" +#include "private_config.hpp" + +#include // must be the last #include + +namespace fs = boost::filesystem; +using boost::system::error_code; +using boost::system::system_category; + +namespace boost { +namespace filesystem { + +//--------------------------------------------------------------------------------------// +// // +// directory_entry // +// // +//--------------------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL void directory_entry::refresh_impl(system::error_code* ec) const +{ + system::error_code local_ec; + m_symlink_status = detail::symlink_status(m_path, &local_ec); + + if (!filesystem::is_symlink(m_symlink_status)) + { + // Also works if symlink_status fails - set m_status to status_error as well + m_status = m_symlink_status; + + if (BOOST_UNLIKELY(!!local_ec)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::directory_entry::refresh", m_path, local_ec)); + + *ec = local_ec; + return; + } + + if (ec) + ec->clear(); + } + else + { + m_status = detail::status(m_path, ec); + } +} + +//--------------------------------------------------------------------------------------// +// // +// directory_iterator // +// // +//--------------------------------------------------------------------------------------// + +namespace detail { + +BOOST_CONSTEXPR_OR_CONST std::size_t dir_itr_imp_extra_data_alignment = 16u; + +BOOST_FILESYSTEM_DECL void* dir_itr_imp::operator new(std::size_t class_size, std::size_t extra_size) BOOST_NOEXCEPT +{ + if (extra_size > 0) + class_size = (class_size + dir_itr_imp_extra_data_alignment - 1u) & ~(dir_itr_imp_extra_data_alignment - 1u); + std::size_t total_size = class_size + extra_size; + + // Return NULL on OOM + void* p = std::malloc(total_size); + if (BOOST_LIKELY(p != NULL)) + std::memset(p, 0, total_size); + return p; +} + +BOOST_FILESYSTEM_DECL void dir_itr_imp::operator delete(void* p, std::size_t extra_size) BOOST_NOEXCEPT +{ + std::free(p); +} + +BOOST_FILESYSTEM_DECL void dir_itr_imp::operator delete(void* p) BOOST_NOEXCEPT +{ + std::free(p); +} + +namespace { + +inline void* get_dir_itr_imp_extra_data(dir_itr_imp* imp) BOOST_NOEXCEPT +{ + BOOST_CONSTEXPR_OR_CONST std::size_t extra_data_offset = (sizeof(dir_itr_imp) + dir_itr_imp_extra_data_alignment - 1u) & ~(dir_itr_imp_extra_data_alignment - 1u); + return reinterpret_cast< unsigned char* >(imp) + extra_data_offset; +} + +#ifdef BOOST_POSIX_API + +inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT +{ + if (imp.handle != NULL) + { + DIR* h = static_cast< DIR* >(imp.handle); + imp.handle = NULL; + int err = 0; + if (BOOST_UNLIKELY(::closedir(h) != 0)) + { + err = errno; + return error_code(err, system_category()); + } + } + + return error_code(); +} + +#if defined(BOOST_FILESYSTEM_USE_READDIR_R) + +// Obtains maximum length of a path, not including the terminating zero +inline std::size_t get_path_max() +{ + // this code is based on Stevens and Rago, Advanced Programming in the + // UNIX envirnment, 2nd Ed., ISBN 0-201-43307-9, page 49 + std::size_t max = 0; + errno = 0; + long res = ::pathconf("/", _PC_PATH_MAX); + if (res < 0) + { +#if defined(PATH_MAX) + max = PATH_MAX; +#else + max = 4096; +#endif + } + else + { + max = static_cast< std::size_t >(res); // relative root +#if defined(PATH_MAX) + if (max < PATH_MAX) + max = PATH_MAX; +#endif + } + + if ((max + 1) < sizeof(dirent().d_name)) + max = sizeof(dirent().d_name) - 1; + + return max; +} + +// Returns maximum length of a path, not including the terminating zero +inline std::size_t path_max() +{ + static const std::size_t max = get_path_max(); + return max; +} + +#endif // BOOST_FILESYSTEM_USE_READDIR_R + +// *result set to NULL on end of directory +#if !defined(BOOST_FILESYSTEM_USE_READDIR_R) +inline +#endif +int readdir_impl(dir_itr_imp& imp, struct dirent** result) +{ + errno = 0; + + struct dirent* p = ::readdir(static_cast< DIR* >(imp.handle)); + *result = p; + if (!p) + return errno; + return 0; +} + +#if !defined(BOOST_FILESYSTEM_USE_READDIR_R) + +inline int invoke_readdir(dir_itr_imp& imp, struct dirent** result) +{ + return readdir_impl(imp, result); +} + +#else // !defined(BOOST_FILESYSTEM_USE_READDIR_R) + +int readdir_r_impl(dir_itr_imp& imp, struct dirent** result) +{ + return ::readdir_r + ( + static_cast< DIR* >(imp.handle), + static_cast< struct dirent* >(get_dir_itr_imp_extra_data(&imp)), + result + ); +} + +int readdir_select_impl(dir_itr_imp& imp, struct dirent** result); + +typedef int readdir_impl_t(dir_itr_imp& imp, struct dirent** result); + +//! Pointer to the actual implementation of the copy_file_data implementation +readdir_impl_t* readdir_impl_ptr = &readdir_select_impl; + +void init_readdir_impl() +{ + readdir_impl_t* impl = &readdir_impl; + if (::sysconf(_SC_THREAD_SAFE_FUNCTIONS) >= 0) + impl = &readdir_r_impl; + + filesystem::detail::atomic_store_relaxed(readdir_impl_ptr, impl); +} + +struct readdir_initializer +{ + readdir_initializer() + { + init_readdir_impl(); + } +}; + +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_FUNC_PTR_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +const readdir_initializer readdir_init; + +int readdir_select_impl(dir_itr_imp& imp, struct dirent** result) +{ + init_readdir_impl(); + return filesystem::detail::atomic_load_relaxed(readdir_impl_ptr)(imp, result); +} + +inline int invoke_readdir(dir_itr_imp& imp, struct dirent** result) +{ + return filesystem::detail::atomic_load_relaxed(readdir_impl_ptr)(imp, result); +} + +#endif // !defined(BOOST_FILESYSTEM_USE_READDIR_R) + +error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + dirent* result = NULL; + int err = invoke_readdir(imp, &result); + if (BOOST_UNLIKELY(err != 0)) + return error_code(err, system_category()); + if (result == NULL) + return dir_itr_close(imp); + + filename = result->d_name; + +#if defined(BOOST_FILESYSTEM_HAS_DIRENT_D_TYPE) + if (result->d_type == DT_UNKNOWN) // filesystem does not supply d_type value + { + sf = symlink_sf = fs::file_status(fs::status_error); + } + else // filesystem supplies d_type value + { + if (result->d_type == DT_REG) + sf = symlink_sf = fs::file_status(fs::regular_file); + else if (result->d_type == DT_DIR) + sf = symlink_sf = fs::file_status(fs::directory_file); + else if (result->d_type == DT_LNK) + { + sf = fs::file_status(fs::status_error); + symlink_sf = fs::file_status(fs::symlink_file); + } + else + { + switch (result->d_type) + { + case DT_SOCK: + sf = symlink_sf = fs::file_status(fs::socket_file); + break; + case DT_FIFO: + sf = symlink_sf = fs::file_status(fs::fifo_file); + break; + case DT_BLK: + sf = symlink_sf = fs::file_status(fs::block_file); + break; + case DT_CHR: + sf = symlink_sf = fs::file_status(fs::character_file); + break; + default: + sf = symlink_sf = fs::file_status(fs::status_error); + break; + } + } + } +#else + sf = symlink_sf = fs::file_status(fs::status_error); +#endif + return error_code(); +} + +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params* params, fs::path& first_filename, fs::file_status&, fs::file_status&) +{ + std::size_t extra_size = 0u; +#if defined(BOOST_FILESYSTEM_USE_READDIR_R) + { + readdir_impl_t* rdimpl = filesystem::detail::atomic_load_relaxed(readdir_impl_ptr); + if (BOOST_UNLIKELY(rdimpl == &readdir_select_impl)) + { + init_readdir_impl(); + rdimpl = filesystem::detail::atomic_load_relaxed(readdir_impl_ptr); + } + + if (rdimpl == &readdir_r_impl) + { + // According to readdir description, there's no reliable way to predict the length of the d_name string. + // It may exceed NAME_MAX and pathconf(_PC_NAME_MAX) limits. We are being conservative here and allocate + // buffer that is enough for PATH_MAX as the directory name. Still, this doesn't guarantee there won't be + // a buffer overrun. The readdir_r API is fundamentally flawed and we should avoid it as much as possible + // in favor of readdir. + extra_size = (sizeof(dirent) - sizeof(dirent().d_name)) + path_max() + 1u; // + 1 for "\0" + } + } +#endif // defined(BOOST_FILESYSTEM_USE_READDIR_R) + + boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (extra_size) detail::dir_itr_imp()); + if (BOOST_UNLIKELY(!pimpl)) + return make_error_code(system::errc::not_enough_memory); + +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + int flags = O_DIRECTORY | O_RDONLY | O_NONBLOCK | O_CLOEXEC; + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + flags |= O_NOFOLLOW; + +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + int fd = ::openat(params ? params->basedir_fd : AT_FDCWD, dir.c_str(), flags); +#else + int fd = ::open(dir.c_str(), flags); +#endif + if (BOOST_UNLIKELY(fd < 0)) + { + const int err = errno; + return error_code(err, system_category()); + } + +#if defined(BOOST_FILESYSTEM_NO_O_CLOEXEC) && defined(FD_CLOEXEC) + int res = ::fcntl(fd, F_SETFD, FD_CLOEXEC); + if (BOOST_UNLIKELY(res < 0)) + { + const int err = errno; + close_fd(fd); + return error_code(err, system_category()); + } +#endif + + pimpl->handle = ::fdopendir(fd); + if (BOOST_UNLIKELY(!pimpl->handle)) + { + const int err = errno; + close_fd(fd); + return error_code(err, system_category()); + } +#else // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + pimpl->handle = ::opendir(dir.c_str()); + if (BOOST_UNLIKELY(!pimpl->handle)) + { + const int err = errno; + return error_code(err, system_category()); + } +#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + + // Force initial readdir call by the caller. This will initialize the actual first filename and statuses. + first_filename.assign("."); + +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + if (params) + params->iterator_fd = fd; +#endif + + imp.swap(pimpl); + return error_code(); +} + +BOOST_CONSTEXPR_OR_CONST err_t not_found_error_code = ENOENT; + +#else // BOOST_WINDOWS_API + +inline void set_file_statuses(DWORD attrs, const ULONG* reparse_point_tag, fs::path const& filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0u) + { + // Reparse points are complex, so don't try to resolve them here; instead just mark + // them as status_error which causes directory_entry caching to call status() + // and symlink_status() which do handle reparse points fully + if (reparse_point_tag) + { + // If we have a reparse point tag we can at least populate the symlink status, + // consistent with symlink_status() behavior + symlink_sf.type(is_reparse_point_tag_a_symlink(*reparse_point_tag) ? fs::symlink_file : fs::reparse_file); + symlink_sf.permissions(make_permissions(filename, attrs)); + } + else + { + symlink_sf.type(fs::status_error); + } + + sf.type(fs::status_error); + } + else + { + if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0u) + { + sf.type(fs::directory_file); + symlink_sf.type(fs::directory_file); + } + else + { + sf.type(fs::regular_file); + symlink_sf.type(fs::regular_file); + } + + sf.permissions(make_permissions(filename, attrs)); + symlink_sf.permissions(sf.permissions()); + } +} + +#if !defined(UNDER_CE) + +//! FILE_ID_128 definition from Windows SDK +struct file_id_128 +{ + BYTE Identifier[16]; +}; + +//! FILE_DIRECTORY_INFORMATION definition from Windows DDK. Used by NtQueryDirectoryFile, supported since Windows NT 4.0 (probably). +struct file_directory_information +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + WCHAR FileName[1]; +}; + +//! FILE_ID_BOTH_DIR_INFO definition from Windows SDK. Basic support for directory iteration using GetFileInformationByHandleEx, supported since Windows Vista. +struct file_id_both_dir_info +{ + DWORD NextEntryOffset; + DWORD FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + DWORD FileAttributes; + DWORD FileNameLength; + DWORD EaSize; + CCHAR ShortNameLength; + WCHAR ShortName[12]; + LARGE_INTEGER FileId; + WCHAR FileName[1]; +}; + +//! FILE_FULL_DIR_INFO definition from Windows SDK. More lightweight than FILE_ID_BOTH_DIR_INFO, supported since Windows 8. +struct file_full_dir_info +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + WCHAR FileName[1]; +}; + +//! FILE_ID_EXTD_DIR_INFO definition from Windows SDK. Provides reparse point tag, which saves us querying it with a few separate syscalls. Supported since Windows 8. +struct file_id_extd_dir_info +{ + ULONG NextEntryOffset; + ULONG FileIndex; + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER EndOfFile; + LARGE_INTEGER AllocationSize; + ULONG FileAttributes; + ULONG FileNameLength; + ULONG EaSize; + ULONG ReparsePointTag; + file_id_128 FileId; + WCHAR FileName[1]; +}; + +//! Indicates format of the extra data in the directory iterator +enum extra_data_format +{ + file_directory_information_format, + file_id_both_dir_info_format, + file_full_dir_info_format, + file_id_extd_dir_info_format +}; + +//! Indicates extra data format that should be used by directory iterator by default +extra_data_format g_extra_data_format = file_directory_information_format; + +/*! + * \brief Extra buffer size for GetFileInformationByHandleEx-based or NtQueryDirectoryFile-based directory iterator. + * + * Must be large enough to accommodate at least one FILE_DIRECTORY_INFORMATION or *_DIR_INFO struct and one filename. + * NTFS, VFAT, exFAT and ReFS support filenames up to 255 UTF-16/UCS-2 characters. (For ReFS, there is no information + * on the on-disk format, and it is possible that it supports longer filenames, up to 32768 UTF-16/UCS-2 characters.) + * The buffer cannot be larger than 64k, because up to Windows 8.1, NtQueryDirectoryFile and GetFileInformationByHandleEx + * fail with ERROR_INVALID_PARAMETER when trying to retrieve the filenames from a network share. + */ +BOOST_CONSTEXPR_OR_CONST std::size_t dir_itr_extra_size = 65536u; + +inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT +{ + imp.extra_data_format = 0u; + imp.current_offset = 0u; + + if (imp.handle != NULL) + { + if (BOOST_LIKELY(imp.close_handle)) + ::CloseHandle(imp.handle); + imp.handle = NULL; + } + + return error_code(); +} + +error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + void* extra_data = get_dir_itr_imp_extra_data(&imp); + const void* current_data = static_cast< const unsigned char* >(extra_data) + imp.current_offset; + switch (imp.extra_data_format) + { + case file_id_extd_dir_info_format: + { + const file_id_extd_dir_info* data = static_cast< const file_id_extd_dir_info* >(current_data); + if (data->NextEntryOffset == 0u) + { + if (!filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api)(imp.handle, file_id_extd_directory_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + dir_itr_close(imp); + if (error == ERROR_NO_MORE_FILES) + goto done; + + return error_code(error, system_category()); + } + + imp.current_offset = 0u; + data = static_cast< const file_id_extd_dir_info* >(extra_data); + } + else + { + imp.current_offset += data->NextEntryOffset; + data = reinterpret_cast< const file_id_extd_dir_info* >(static_cast< const unsigned char* >(current_data) + data->NextEntryOffset); + } + + filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + set_file_statuses(data->FileAttributes, &data->ReparsePointTag, filename, sf, symlink_sf); + } + break; + + case file_full_dir_info_format: + { + const file_full_dir_info* data = static_cast< const file_full_dir_info* >(current_data); + if (data->NextEntryOffset == 0u) + { + if (!filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api)(imp.handle, file_full_directory_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + dir_itr_close(imp); + if (error == ERROR_NO_MORE_FILES) + goto done; + + return error_code(error, system_category()); + } + + imp.current_offset = 0u; + data = static_cast< const file_full_dir_info* >(extra_data); + } + else + { + imp.current_offset += data->NextEntryOffset; + data = reinterpret_cast< const file_full_dir_info* >(static_cast< const unsigned char* >(current_data) + data->NextEntryOffset); + } + + filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + set_file_statuses(data->FileAttributes, NULL, filename, sf, symlink_sf); + } + break; + + case file_id_both_dir_info_format: + { + const file_id_both_dir_info* data = static_cast< const file_id_both_dir_info* >(current_data); + if (data->NextEntryOffset == 0u) + { + if (!filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api)(imp.handle, file_id_both_directory_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + dir_itr_close(imp); + if (error == ERROR_NO_MORE_FILES) + goto done; + + return error_code(error, system_category()); + } + + imp.current_offset = 0u; + data = static_cast< const file_id_both_dir_info* >(extra_data); + } + else + { + imp.current_offset += data->NextEntryOffset; + data = reinterpret_cast< const file_id_both_dir_info* >(static_cast< const unsigned char* >(current_data) + data->NextEntryOffset); + } + + filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + set_file_statuses(data->FileAttributes, NULL, filename, sf, symlink_sf); + } + break; + + default: + { + const file_directory_information* data = static_cast< const file_directory_information* >(current_data); + if (data->NextEntryOffset == 0u) + { + io_status_block iosb; + boost::winapi::NTSTATUS_ status = filesystem::detail::atomic_load_relaxed(nt_query_directory_file_api) + ( + imp.handle, + NULL, // Event + NULL, // ApcRoutine + NULL, // ApcContext + &iosb, + extra_data, + dir_itr_extra_size, + file_directory_information_class, + FALSE, // ReturnSingleEntry + NULL, // FileName + FALSE // RestartScan + ); + + if (!NT_SUCCESS(status)) + { + dir_itr_close(imp); + if (status == STATUS_NO_MORE_FILES) + goto done; + + return error_code(translate_ntstatus(status), system_category()); + } + + imp.current_offset = 0u; + data = static_cast< const file_directory_information* >(extra_data); + } + else + { + imp.current_offset += data->NextEntryOffset; + data = reinterpret_cast< const file_directory_information* >(static_cast< const unsigned char* >(current_data) + data->NextEntryOffset); + } + + filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + set_file_statuses(data->FileAttributes, NULL, filename, sf, symlink_sf); + } + break; + } + +done: + return error_code(); +} + +//! Returns \c true if the error code indicates that the OS or the filesystem does not support a particular directory info class +inline bool is_dir_info_class_not_supported(DWORD error) +{ + // Some mounted filesystems may not support FILE_ID_128 identifiers, which will cause + // GetFileInformationByHandleEx(FileIdExtdDirectoryRestartInfo) return ERROR_INVALID_PARAMETER, + // even though in general the operation is supported by the kernel. SMBv1 returns a special error + // code ERROR_INVALID_LEVEL in this case. + // Some other filesystems also don't implement other info classes and return ERROR_INVALID_PARAMETER + // (e.g. see https://github.com/boostorg/filesystem/issues/266), ERROR_GEN_FAILURE, ERROR_INVALID_FUNCTION + // or ERROR_INTERNAL_ERROR (https://github.com/boostorg/filesystem/issues/286). Treat these error codes + // as "non-permanent", even though ERROR_INVALID_PARAMETER is also returned if GetFileInformationByHandleEx + // in general does not support a certain info class. Worst case, we will make extra syscalls on directory + // iterator construction. + // Also note that Wine returns ERROR_CALL_NOT_IMPLEMENTED for unimplemented info classes, and + // up until 7.21 it didn't implement FileIdExtdDirectoryRestartInfo and FileFullDirectoryRestartInfo. + // (https://bugs.winehq.org/show_bug.cgi?id=53590) + return error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER || + error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED || + error == ERROR_GEN_FAILURE || error == ERROR_INVALID_FUNCTION || + error == ERROR_INTERNAL_ERROR; +} + +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params* params, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (dir_itr_extra_size) detail::dir_itr_imp()); + if (BOOST_UNLIKELY(!pimpl)) + return make_error_code(system::errc::not_enough_memory); + + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); + + handle_wrapper h; + HANDLE iterator_handle; + bool close_handle = true; + if (params != NULL && params->use_handle != INVALID_HANDLE_VALUE) + { + // Operate on externally provided handle, which must be a directory handle + iterator_handle = params->use_handle; + close_handle = params->close_handle; + } + else + { + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + + iterator_handle = h.handle = create_file_handle(dir, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flags); + if (BOOST_UNLIKELY(iterator_handle == INVALID_HANDLE_VALUE)) + { + return_last_error: + DWORD error = ::GetLastError(); + return error_code(error, system_category()); + } + + if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) + { + file_attribute_tag_info info; + BOOL res = get_file_information_by_handle_ex(iterator_handle, file_attribute_tag_info_class, &info, sizeof(info)); + if (BOOST_UNLIKELY(!res)) + { + // On FAT/exFAT filesystems requesting FILE_ATTRIBUTE_TAG_INFO returns ERROR_INVALID_PARAMETER. See the comment in symlink_status. + DWORD error = ::GetLastError(); + if (error == ERROR_INVALID_PARAMETER || error == ERROR_NOT_SUPPORTED) + goto use_get_file_information_by_handle; + + return error_code(error, system_category()); + } + + if (BOOST_UNLIKELY((info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) + return make_error_code(system::errc::not_a_directory); + + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + { + if ((info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_tag_a_symlink(info.ReparseTag)) + return make_error_code(system::errc::too_many_symbolic_link_levels); + } + } + else + { + use_get_file_information_by_handle: + BY_HANDLE_FILE_INFORMATION info; + BOOL res = ::GetFileInformationByHandle(iterator_handle, &info); + if (BOOST_UNLIKELY(!res)) + goto return_last_error; + + if (BOOST_UNLIKELY((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) + return make_error_code(system::errc::not_a_directory); + + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u && (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u) + { + error_code ec; + const ULONG reparse_point_tag = detail::get_reparse_point_tag_ioctl(h.handle, dir, &ec); + if (BOOST_UNLIKELY(!!ec)) + return ec; + + if (detail::is_reparse_point_tag_a_symlink(reparse_point_tag)) + return make_error_code(system::errc::too_many_symbolic_link_levels); + } + } + } + + void* extra_data = get_dir_itr_imp_extra_data(pimpl.get()); + switch (filesystem::detail::atomic_load_relaxed(g_extra_data_format)) + { + case file_id_extd_dir_info_format: + { + if (!get_file_information_by_handle_ex(iterator_handle, file_id_extd_directory_restart_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + if (is_dir_info_class_not_supported(error)) + { + // Fall back to file_full_dir_info_format. + if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED) + filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_full_dir_info_format); + goto fallback_to_file_full_dir_info_format; + } + + if (error == ERROR_NO_MORE_FILES || error == ERROR_FILE_NOT_FOUND) + goto done; + + return error_code(error, system_category()); + } + + pimpl->extra_data_format = file_id_extd_dir_info_format; + + const file_id_extd_dir_info* data = static_cast< const file_id_extd_dir_info* >(extra_data); + first_filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + + set_file_statuses(data->FileAttributes, &data->ReparsePointTag, first_filename, sf, symlink_sf); + } + break; + + case file_full_dir_info_format: + fallback_to_file_full_dir_info_format: + { + if (!get_file_information_by_handle_ex(iterator_handle, file_full_directory_restart_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + if (is_dir_info_class_not_supported(error)) + { + // Fall back to file_id_both_dir_info + if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED) + filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_id_both_dir_info_format); + goto fallback_to_file_id_both_dir_info_format; + } + + if (error == ERROR_NO_MORE_FILES || error == ERROR_FILE_NOT_FOUND) + goto done; + + return error_code(error, system_category()); + } + + pimpl->extra_data_format = file_full_dir_info_format; + + const file_full_dir_info* data = static_cast< const file_full_dir_info* >(extra_data); + first_filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + + set_file_statuses(data->FileAttributes, NULL, first_filename, sf, symlink_sf); + } + break; + + case file_id_both_dir_info_format: + fallback_to_file_id_both_dir_info_format: + { + if (!get_file_information_by_handle_ex(iterator_handle, file_id_both_directory_restart_info_class, extra_data, dir_itr_extra_size)) + { + DWORD error = ::GetLastError(); + + if (is_dir_info_class_not_supported(error)) + { + // Fall back to file_directory_information + if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED) + filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_directory_information_format); + goto fallback_to_file_directory_information_format; + } + + if (error == ERROR_NO_MORE_FILES || error == ERROR_FILE_NOT_FOUND) + goto done; + + return error_code(error, system_category()); + } + + pimpl->extra_data_format = file_id_both_dir_info_format; + + const file_id_both_dir_info* data = static_cast< const file_id_both_dir_info* >(extra_data); + first_filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + + set_file_statuses(data->FileAttributes, NULL, first_filename, sf, symlink_sf); + } + break; + + default: + fallback_to_file_directory_information_format: + { + NtQueryDirectoryFile_t* nt_query_directory_file = filesystem::detail::atomic_load_relaxed(boost::filesystem::detail::nt_query_directory_file_api); + if (BOOST_UNLIKELY(!nt_query_directory_file)) + return error_code(ERROR_NOT_SUPPORTED, system_category()); + + io_status_block iosb; + boost::winapi::NTSTATUS_ status = nt_query_directory_file + ( + iterator_handle, + NULL, // Event + NULL, // ApcRoutine + NULL, // ApcContext + &iosb, + extra_data, + dir_itr_extra_size, + file_directory_information_class, + FALSE, // ReturnSingleEntry + NULL, // FileName + TRUE // RestartScan + ); + + if (!NT_SUCCESS(status)) + { + // Note: an empty root directory has no "." or ".." entries, so this + // causes a ERROR_FILE_NOT_FOUND error returned from FindFirstFileW + // (which is presumably equivalent to STATUS_NO_SUCH_FILE) which we + // do not consider an error. It is treated as eof instead. + if (status == STATUS_NO_MORE_FILES || status == STATUS_NO_SUCH_FILE) + goto done; + + return error_code(translate_ntstatus(status), system_category()); + } + + pimpl->extra_data_format = file_directory_information_format; + + const file_directory_information* data = static_cast< const file_directory_information* >(extra_data); + first_filename.assign(data->FileName, data->FileName + data->FileNameLength / sizeof(WCHAR)); + + set_file_statuses(data->FileAttributes, NULL, first_filename, sf, symlink_sf); + } + break; + } + + + pimpl->handle = iterator_handle; + h.handle = INVALID_HANDLE_VALUE; + pimpl->close_handle = close_handle; + +done: + imp.swap(pimpl); + return error_code(); +} + +#else // !defined(UNDER_CE) + +inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT +{ + if (imp.handle != NULL) + { + if (BOOST_LIKELY(imp.close_handle)) + ::FindClose(imp.handle); + imp.handle = NULL; + } + + return error_code(); +} + +error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + WIN32_FIND_DATAW data; + if (::FindNextFileW(imp.handle, &data) == 0) // fails + { + DWORD error = ::GetLastError(); + dir_itr_close(imp); + if (error == ERROR_NO_MORE_FILES) + goto done; + return error_code(error, system_category()); + } + + filename = data.cFileName; + set_file_statuses(data.dwFileAttributes, NULL, filename, sf, symlink_sf); + +done: + return error_code(); +} + +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params*, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) +{ + boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (static_cast< std::size_t >(0u)) detail::dir_itr_imp()); + if (BOOST_UNLIKELY(!pimpl)) + return make_error_code(system::errc::not_enough_memory); + + // use a form of search Sebastian Martel reports will work with Win98 + fs::path dirpath(dir); + dirpath.make_preferred(); + dirpath /= L"*"; + + WIN32_FIND_DATAW data; + pimpl->handle = ::FindFirstFileW(dirpath.c_str(), &data); + if (BOOST_UNLIKELY(pimpl->handle == INVALID_HANDLE_VALUE)) + { + pimpl->handle = NULL; // signal eof + + // Note: an empty root directory has no "." or ".." entries, so this + // causes a ERROR_FILE_NOT_FOUND error which we do not consider an + // error. It is treated as eof instead. + // Windows Mobile returns ERROR_NO_MORE_FILES; see ticket #3551 + DWORD error = ::GetLastError(); + if (error == ERROR_FILE_NOT_FOUND || error == ERROR_NO_MORE_FILES) + goto done; + + return error_code(error, system_category()); + } + + pimpl->close_handle = true; + + first_filename = data.cFileName; + set_file_statuses(data.dwFileAttributes, NULL, first_filename, sf, symlink_sf); + +done: + imp.swap(pimpl); + return error_code(); +} + +#endif // !defined(UNDER_CE) + +BOOST_CONSTEXPR_OR_CONST err_t not_found_error_code = ERROR_PATH_NOT_FOUND; + +#endif // BOOST_WINDOWS_API + +} // namespace + +#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) + +//! Initializes directory iterator implementation +void init_directory_iterator_impl() BOOST_NOEXCEPT +{ + if (filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api) != NULL) + { + // Enable the latest format we support. It will get downgraded, if needed, as we attempt + // to create the directory iterator the first time. + filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_id_extd_dir_info_format); + } +} + +#endif // defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) + +BOOST_FILESYSTEM_DECL +dir_itr_imp::~dir_itr_imp() BOOST_NOEXCEPT +{ + dir_itr_close(*this); +} + +BOOST_FILESYSTEM_DECL +void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec) +{ + if (BOOST_UNLIKELY(p.empty())) + { + emit_error(not_found_error_code, p, ec, "boost::filesystem::directory_iterator::construct"); + return; + } + + if (ec) + ec->clear(); + + try + { + boost::intrusive_ptr< detail::dir_itr_imp > imp; + path filename; + file_status file_stat, symlink_file_stat; + system::error_code result = dir_itr_create(imp, p, opts, params, filename, file_stat, symlink_file_stat); + + while (true) + { + if (result) + { + if (result != make_error_condition(system::errc::permission_denied) || + (opts & static_cast< unsigned int >(directory_options::skip_permission_denied)) == 0u) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::directory_iterator::construct", p, result)); + *ec = result; + } + + return; + } + + if (imp->handle == NULL) // eof, make end + return; + + // Not eof + const path::string_type::value_type* filename_str = filename.c_str(); + if (!(filename_str[0] == path::dot // dot or dot-dot + && (filename_str[1] == static_cast< path::string_type::value_type >('\0') || + (filename_str[1] == path::dot && filename_str[2] == static_cast< path::string_type::value_type >('\0'))))) + { + path full_path(p); + path_algorithms::append_v4(full_path, filename); + imp->dir_entry.assign_with_status + ( +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + static_cast< path&& >(full_path), +#else + full_path, +#endif + file_stat, + symlink_file_stat + ); + it.m_imp.swap(imp); + return; + } + + // If dot or dot-dot name produced by the underlying API, skip it until the first actual file + result = dir_itr_increment(*imp, filename, file_stat, symlink_file_stat); + } + } + catch (std::bad_alloc&) + { + if (!ec) + throw; + + *ec = make_error_code(system::errc::not_enough_memory); + it.m_imp.reset(); + } +} + +BOOST_FILESYSTEM_DECL +void directory_iterator_increment(directory_iterator& it, system::error_code* ec) +{ + BOOST_ASSERT_MSG(!it.is_end(), "attempt to increment end iterator"); + + if (ec) + ec->clear(); + + try + { + path filename; + file_status file_stat, symlink_file_stat; + system::error_code increment_ec; + + while (true) + { + increment_ec = dir_itr_increment(*it.m_imp, filename, file_stat, symlink_file_stat); + + if (BOOST_UNLIKELY(!!increment_ec)) // happens if filesystem is corrupt, such as on a damaged optical disc + { + boost::intrusive_ptr< detail::dir_itr_imp > imp; + imp.swap(it.m_imp); + path error_path(imp->dir_entry.path().parent_path()); // fix ticket #5900 + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::directory_iterator::operator++", error_path, increment_ec)); + + *ec = increment_ec; + return; + } + + if (it.m_imp->handle == NULL) // eof, make end + { + it.m_imp.reset(); + return; + } + + const path::string_type::value_type* filename_str = filename.c_str(); + if (!(filename_str[0] == path::dot // !(dot or dot-dot) + && (filename_str[1] == static_cast< path::string_type::value_type >('\0') || + (filename_str[1] == path::dot && filename_str[2] == static_cast< path::string_type::value_type >('\0'))))) + { + it.m_imp->dir_entry.replace_filename_with_status(filename, file_stat, symlink_file_stat); + return; + } + } + } + catch (std::bad_alloc&) + { + if (!ec) + throw; + + it.m_imp.reset(); + *ec = make_error_code(system::errc::not_enough_memory); + } +} + +//--------------------------------------------------------------------------------------// +// // +// recursive_directory_iterator // +// // +//--------------------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL +void recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, unsigned int opts, system::error_code* ec) +{ + if (ec) + ec->clear(); + + directory_iterator dir_it; + detail::directory_iterator_construct(dir_it, dir_path, opts, NULL, ec); + if ((ec && *ec) || dir_it == directory_iterator()) + return; + + boost::intrusive_ptr< detail::recur_dir_itr_imp > imp; + if (!ec) + { + imp = new detail::recur_dir_itr_imp(opts); + } + else + { + imp = new (std::nothrow) detail::recur_dir_itr_imp(opts); + if (BOOST_UNLIKELY(!imp)) + { + *ec = make_error_code(system::errc::not_enough_memory); + return; + } + } + + try + { +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + imp->m_stack.push_back(std::move(dir_it)); +#else + imp->m_stack.push_back(dir_it); +#endif + + it.m_imp.swap(imp); + } + catch (std::bad_alloc&) + { + if (ec) + { + *ec = make_error_code(system::errc::not_enough_memory); + return; + } + + throw; + } +} + +namespace { + +void recursive_directory_iterator_pop_on_error(detail::recur_dir_itr_imp* imp) +{ + imp->m_stack.pop_back(); + + while (!imp->m_stack.empty()) + { + directory_iterator& dir_it = imp->m_stack.back(); + system::error_code increment_ec; + detail::directory_iterator_increment(dir_it, &increment_ec); + if (!increment_ec && dir_it != directory_iterator()) + break; + + imp->m_stack.pop_back(); + } +} + +} // namespace + +BOOST_FILESYSTEM_DECL +void recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec) +{ + BOOST_ASSERT_MSG(!it.is_end(), "pop() on end recursive_directory_iterator"); + detail::recur_dir_itr_imp* const imp = it.m_imp.get(); + + if (ec) + ec->clear(); + + imp->m_stack.pop_back(); + + while (true) + { + if (imp->m_stack.empty()) + { + it.m_imp.reset(); // done, so make end iterator + break; + } + + directory_iterator& dir_it = imp->m_stack.back(); + system::error_code increment_ec; + detail::directory_iterator_increment(dir_it, &increment_ec); + if (BOOST_UNLIKELY(!!increment_ec)) + { + if ((imp->m_options & static_cast< unsigned int >(directory_options::pop_on_error)) == 0u) + { + // Make an end iterator on errors + it.m_imp.reset(); + } + else + { + recursive_directory_iterator_pop_on_error(imp); + + if (imp->m_stack.empty()) + it.m_imp.reset(); // done, so make end iterator + } + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::recursive_directory_iterator::pop", increment_ec)); + + *ec = increment_ec; + return; + } + + if (dir_it != directory_iterator()) + break; + + imp->m_stack.pop_back(); + } +} + +namespace { + +enum push_directory_result +{ + directory_not_pushed = 0u, + directory_pushed = 1u, + keep_depth = 1u << 1 +}; + +// Returns: true if push occurs, otherwise false. Always returns false on error. +inline push_directory_result recursive_directory_iterator_push_directory(detail::recur_dir_itr_imp* imp, system::error_code& ec) BOOST_NOEXCEPT +{ + push_directory_result result = directory_not_pushed; + try + { + // Discover if the iterator is for a directory that needs to be recursed into, + // taking symlinks and options into account. + + if ((imp->m_options & static_cast< unsigned int >(directory_options::_detail_no_push)) != 0u) + { + imp->m_options &= ~static_cast< unsigned int >(directory_options::_detail_no_push); + return result; + } + + file_type symlink_ft = status_error; + + // If we are not recursing into symlinks, we are going to have to know if the + // stack top is a symlink, so get symlink_status and verify no error occurred. + if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) == 0u || + (imp->m_options & static_cast< unsigned int >(directory_options::skip_dangling_symlinks)) != 0u) + { + symlink_ft = imp->m_stack.back()->symlink_file_type(ec); + if (ec) + return result; + } + + // Logic for following predicate was contributed by Daniel Aarno to handle cyclic + // symlinks correctly and efficiently, fixing ticket #5652. + // if (((m_options & directory_options::follow_directory_symlink) == directory_options::follow_directory_symlink + // || !is_symlink(m_stack.back()->symlink_status())) + // && is_directory(m_stack.back()->status())) ... + // The predicate code has since been rewritten to pass error_code arguments, + // per ticket #5653. + + if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) != 0u || symlink_ft != symlink_file) + { + file_type ft = imp->m_stack.back()->file_type(ec); + if (BOOST_UNLIKELY(!!ec)) + { + if (ec == make_error_condition(system::errc::no_such_file_or_directory) && symlink_ft == symlink_file && + (imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) == static_cast< unsigned int >(directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) + { + // Skip dangling symlink and continue iteration on the current depth level + ec = error_code(); + } + + return result; + } + + if (ft != directory_file) + return result; + + if (BOOST_UNLIKELY((imp->m_stack.size() - 1u) >= static_cast< std::size_t >((std::numeric_limits< int >::max)()))) + { + // We cannot let depth to overflow + ec = make_error_code(system::errc::value_too_large); + // When depth overflow happens, avoid popping the current directory iterator + // and attempt to continue iteration on the current depth. + result = keep_depth; + return result; + } + + directory_iterator next(imp->m_stack.back()->path(), static_cast< BOOST_SCOPED_ENUM_NATIVE(directory_options) >(imp->m_options), ec); + if (!ec && next != directory_iterator()) + { +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + imp->m_stack.push_back(std::move(next)); // may throw +#else + imp->m_stack.push_back(next); // may throw +#endif + return directory_pushed; + } + } + } + catch (std::bad_alloc&) + { + ec = make_error_code(system::errc::not_enough_memory); + } + + return result; +} + +} // namespace + +BOOST_FILESYSTEM_DECL +void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec) +{ + BOOST_ASSERT_MSG(!it.is_end(), "increment() on end recursive_directory_iterator"); + detail::recur_dir_itr_imp* const imp = it.m_imp.get(); + + if (ec) + ec->clear(); + + system::error_code local_ec; + + // if various conditions are met, push a directory_iterator into the iterator stack + push_directory_result push_result = recursive_directory_iterator_push_directory(imp, local_ec); + if (push_result == directory_pushed) + return; + + // report errors if any + if (BOOST_UNLIKELY(!!local_ec)) + { + on_error: + if ((imp->m_options & static_cast< unsigned int >(directory_options::pop_on_error)) == 0u) + { + // Make an end iterator on errors + it.m_imp.reset(); + } + else + { + if ((push_result & keep_depth) != 0u) + { + system::error_code increment_ec; + directory_iterator& dir_it = imp->m_stack.back(); + detail::directory_iterator_increment(dir_it, &increment_ec); + if (!increment_ec && dir_it != directory_iterator()) + goto on_error_return; + } + + recursive_directory_iterator_pop_on_error(imp); + + if (imp->m_stack.empty()) + it.m_imp.reset(); // done, so make end iterator + } + + on_error_return: + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("filesystem::recursive_directory_iterator increment error", local_ec)); + + *ec = local_ec; + return; + } + + // Do the actual increment operation on the top iterator in the iterator + // stack, popping the stack if necessary, until either the stack is empty or a + // non-end iterator is reached. + while (true) + { + if (imp->m_stack.empty()) + { + it.m_imp.reset(); // done, so make end iterator + break; + } + + directory_iterator& dir_it = imp->m_stack.back(); + detail::directory_iterator_increment(dir_it, &local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + goto on_error; + + if (dir_it != directory_iterator()) + break; + + imp->m_stack.pop_back(); + } +} + +} // namespace detail + +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/error_handling.hpp b/libs/filesystem/src/error_handling.hpp new file mode 100644 index 0000000..97590a8 --- /dev/null +++ b/libs/filesystem/src/error_handling.hpp @@ -0,0 +1,220 @@ +// error_handling.hpp --------------------------------------------------------------------// + +// Copyright 2002-2009, 2014 Beman Dawes +// Copyright 2019 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ +#define BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ + +#include +#include +#include +#include + +#if defined(BOOST_WINDOWS_API) +#include +#include +#include +#endif + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +#if defined(BOOST_POSIX_API) + +typedef int err_t; + +// POSIX uses a 0 return to indicate success +#define BOOST_ERRNO errno + +#define BOOST_ERROR_FILE_NOT_FOUND ENOENT +#define BOOST_ERROR_ALREADY_EXISTS EEXIST +#define BOOST_ERROR_NOT_SUPPORTED ENOSYS + +#else + +typedef boost::winapi::DWORD_ err_t; + +// Windows uses a non-0 return to indicate success +#define BOOST_ERRNO boost::winapi::GetLastError() + +#define BOOST_ERROR_FILE_NOT_FOUND boost::winapi::ERROR_FILE_NOT_FOUND_ +#define BOOST_ERROR_ALREADY_EXISTS boost::winapi::ERROR_ALREADY_EXISTS_ +#define BOOST_ERROR_NOT_SUPPORTED boost::winapi::ERROR_NOT_SUPPORTED_ + +// Note: Legacy MinGW doesn't have ntstatus.h and doesn't define NTSTATUS error codes other than STATUS_SUCCESS. +#if !defined(NT_SUCCESS) +#define NT_SUCCESS(Status) (((boost::winapi::NTSTATUS_)(Status)) >= 0) +#endif +#if !defined(STATUS_SUCCESS) +#define STATUS_SUCCESS ((boost::winapi::NTSTATUS_)0x00000000l) +#endif +#if !defined(STATUS_NOT_IMPLEMENTED) +#define STATUS_NOT_IMPLEMENTED ((boost::winapi::NTSTATUS_)0xC0000002l) +#endif +#if !defined(STATUS_INVALID_INFO_CLASS) +#define STATUS_INVALID_INFO_CLASS ((boost::winapi::NTSTATUS_)0xC0000003l) +#endif +#if !defined(STATUS_INVALID_HANDLE) +#define STATUS_INVALID_HANDLE ((boost::winapi::NTSTATUS_)0xC0000008l) +#endif +#if !defined(STATUS_INVALID_PARAMETER) +#define STATUS_INVALID_PARAMETER ((boost::winapi::NTSTATUS_)0xC000000Dl) +#endif +#if !defined(STATUS_NO_SUCH_DEVICE) +#define STATUS_NO_SUCH_DEVICE ((boost::winapi::NTSTATUS_)0xC000000El) +#endif +#if !defined(STATUS_NO_SUCH_FILE) +#define STATUS_NO_SUCH_FILE ((boost::winapi::NTSTATUS_)0xC000000Fl) +#endif +#if !defined(STATUS_NO_MORE_FILES) +#define STATUS_NO_MORE_FILES ((boost::winapi::NTSTATUS_)0x80000006l) +#endif +#if !defined(STATUS_BUFFER_OVERFLOW) +#define STATUS_BUFFER_OVERFLOW ((boost::winapi::NTSTATUS_)0x80000005l) +#endif +#if !defined(STATUS_NO_MEMORY) +#define STATUS_NO_MEMORY ((boost::winapi::NTSTATUS_)0xC0000017l) +#endif +#if !defined(STATUS_ACCESS_DENIED) +#define STATUS_ACCESS_DENIED ((boost::winapi::NTSTATUS_)0xC0000022l) +#endif +#if !defined(STATUS_OBJECT_NAME_NOT_FOUND) +#define STATUS_OBJECT_NAME_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000034l) +#endif +#if !defined(STATUS_OBJECT_PATH_NOT_FOUND) +#define STATUS_OBJECT_PATH_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC000003Al) +#endif +#if !defined(STATUS_NOT_SUPPORTED) +#define STATUS_NOT_SUPPORTED ((boost::winapi::NTSTATUS_)0xC00000BBl) +#endif +#if !defined(STATUS_BAD_NETWORK_PATH) +#define STATUS_BAD_NETWORK_PATH ((boost::winapi::NTSTATUS_)0xC00000BEl) +#endif +#if !defined(STATUS_DEVICE_DOES_NOT_EXIST) +#define STATUS_DEVICE_DOES_NOT_EXIST ((boost::winapi::NTSTATUS_)0xC00000C0l) +#endif +#if !defined(STATUS_BAD_NETWORK_NAME) +#define STATUS_BAD_NETWORK_NAME ((boost::winapi::NTSTATUS_)0xC00000CCl) +#endif +#if !defined(STATUS_DIRECTORY_NOT_EMPTY) +#define STATUS_DIRECTORY_NOT_EMPTY ((boost::winapi::NTSTATUS_)0xC0000101l) +#endif +#if !defined(STATUS_NOT_A_DIRECTORY) +#define STATUS_NOT_A_DIRECTORY ((boost::winapi::NTSTATUS_)0xC0000103l) +#endif +#if !defined(STATUS_NOT_FOUND) +#define STATUS_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000225l) +#endif + +//! Converts NTSTATUS error codes to Win32 error codes for reporting +inline boost::winapi::DWORD_ translate_ntstatus(boost::winapi::NTSTATUS_ status) +{ + // We have to cast to unsigned integral type to avoid signed overflow and narrowing conversion in the constants. + switch (static_cast< boost::winapi::ULONG_ >(status)) + { + case static_cast< boost::winapi::ULONG_ >(STATUS_NO_MEMORY): + return boost::winapi::ERROR_OUTOFMEMORY_; + case static_cast< boost::winapi::ULONG_ >(STATUS_BUFFER_OVERFLOW): + return boost::winapi::ERROR_BUFFER_OVERFLOW_; + case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_HANDLE): + return boost::winapi::ERROR_INVALID_HANDLE_; + case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_PARAMETER): + return boost::winapi::ERROR_INVALID_PARAMETER_; + case static_cast< boost::winapi::ULONG_ >(STATUS_NO_MORE_FILES): + return boost::winapi::ERROR_NO_MORE_FILES_; + case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_DEVICE): + case static_cast< boost::winapi::ULONG_ >(STATUS_DEVICE_DOES_NOT_EXIST): + return boost::winapi::ERROR_DEV_NOT_EXIST_; + case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_FILE): + case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_NAME_NOT_FOUND): + case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_PATH_NOT_FOUND): + return boost::winapi::ERROR_FILE_NOT_FOUND_; + case static_cast< boost::winapi::ULONG_ >(STATUS_ACCESS_DENIED): + return boost::winapi::ERROR_ACCESS_DENIED_; + case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_PATH): + return boost::winapi::ERROR_BAD_NETPATH_; + case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_NAME): + return boost::winapi::ERROR_BAD_NET_NAME_; + case static_cast< boost::winapi::ULONG_ >(STATUS_DIRECTORY_NOT_EMPTY): + return boost::winapi::ERROR_DIR_NOT_EMPTY_; + case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_A_DIRECTORY): + return boost::winapi::ERROR_DIRECTORY_; // The directory name is invalid + case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_FOUND): + return boost::winapi::ERROR_NOT_FOUND_; + // map "invalid info class" to "not supported" as this error likely indicates that the kernel does not support what we request + case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_INFO_CLASS): + default: + return boost::winapi::ERROR_NOT_SUPPORTED_; + } +} + +#endif + +// error handling helpers ----------------------------------------------------------// + +// Implemented in exception.cpp +void emit_error(err_t error_num, system::error_code* ec, const char* message); +void emit_error(err_t error_num, path const& p, system::error_code* ec, const char* message); +void emit_error(err_t error_num, path const& p1, path const& p2, system::error_code* ec, const char* message); + +inline bool error(err_t error_num, system::error_code* ec, const char* message) +{ + if (BOOST_LIKELY(!error_num)) + { + if (ec) + ec->clear(); + return false; + } + else + { // error + filesystem::emit_error(error_num, ec, message); + return true; + } +} + +inline bool error(err_t error_num, path const& p, system::error_code* ec, const char* message) +{ + if (BOOST_LIKELY(!error_num)) + { + if (ec) + ec->clear(); + return false; + } + else + { // error + filesystem::emit_error(error_num, p, ec, message); + return true; + } +} + +inline bool error(err_t error_num, path const& p1, path const& p2, system::error_code* ec, const char* message) +{ + if (BOOST_LIKELY(!error_num)) + { + if (ec) + ec->clear(); + return false; + } + else + { // error + filesystem::emit_error(error_num, p1, p2, ec, message); + return true; + } +} + +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ diff --git a/libs/filesystem/src/exception.cpp b/libs/filesystem/src/exception.cpp new file mode 100644 index 0000000..91ee1c9 --- /dev/null +++ b/libs/filesystem/src/exception.cpp @@ -0,0 +1,188 @@ +// boost/filesystem/exception.hpp -----------------------------------------------------// + +// Copyright Beman Dawes 2003 +// Copyright Andrey Semashev 2019 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include +#include +#include +#include + +#include "error_handling.hpp" + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(const char* what_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl()); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(std::string const& what_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl()); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(const char* what_arg, path const& path1_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl(path1_arg)); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(std::string const& what_arg, path const& path1_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl(path1_arg)); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(const char* what_arg, path const& path1_arg, path const& path2_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl(path1_arg, path2_arg)); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(std::string const& what_arg, path const& path1_arg, path const& path2_arg, system::error_code ec) : + system::system_error(ec, what_arg) +{ + try + { + m_imp_ptr.reset(new impl(path1_arg, path2_arg)); + } + catch (...) + { + m_imp_ptr.reset(); + } +} + +BOOST_FILESYSTEM_DECL filesystem_error::filesystem_error(filesystem_error const& that) : + system::system_error(static_cast< system::system_error const& >(that)), + m_imp_ptr(that.m_imp_ptr) +{ +} + +BOOST_FILESYSTEM_DECL filesystem_error& filesystem_error::operator=(filesystem_error const& that) +{ + static_cast< system::system_error& >(*this) = static_cast< system::system_error const& >(that); + m_imp_ptr = that.m_imp_ptr; + return *this; +} + +BOOST_FILESYSTEM_DECL filesystem_error::~filesystem_error() BOOST_NOEXCEPT_OR_NOTHROW +{ +} + +BOOST_FILESYSTEM_DECL const char* filesystem_error::what() const BOOST_NOEXCEPT_OR_NOTHROW +{ + if (m_imp_ptr.get()) try + { + if (m_imp_ptr->m_what.empty()) + { + m_imp_ptr->m_what = system::system_error::what(); + if (!m_imp_ptr->m_path1.empty()) + { + m_imp_ptr->m_what += ": \""; + m_imp_ptr->m_what += m_imp_ptr->m_path1.string(); + m_imp_ptr->m_what += "\""; + } + if (!m_imp_ptr->m_path2.empty()) + { + m_imp_ptr->m_what += ", \""; + m_imp_ptr->m_what += m_imp_ptr->m_path2.string(); + m_imp_ptr->m_what += "\""; + } + } + + return m_imp_ptr->m_what.c_str(); + } + catch (...) + { + m_imp_ptr->m_what.clear(); + } + + return system::system_error::what(); +} + +BOOST_FILESYSTEM_DECL path const& filesystem_error::get_empty_path() BOOST_NOEXCEPT +{ + static const path empty_path; + return empty_path; +} + +// error handling helpers declared in error_handling.hpp -----------------------------------------------------// + +void emit_error(err_t error_num, system::error_code* ec, const char* message) +{ + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error(message, system::error_code(error_num, system::system_category()))); + else + ec->assign(error_num, system::system_category()); +} + +void emit_error(err_t error_num, path const& p, system::error_code* ec, const char* message) +{ + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error(message, p, system::error_code(error_num, system::system_category()))); + else + ec->assign(error_num, system::system_category()); +} + +void emit_error(err_t error_num, path const& p1, path const& p2, system::error_code* ec, const char* message) +{ + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error(message, p1, p2, system::error_code(error_num, system::system_category()))); + else + ec->assign(error_num, system::system_category()); +} + +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/operations.cpp b/libs/filesystem/src/operations.cpp new file mode 100644 index 0000000..c7808d5 --- /dev/null +++ b/libs/filesystem/src/operations.cpp @@ -0,0 +1,4614 @@ +// operations.cpp --------------------------------------------------------------------// + +// Copyright 2002-2009, 2014 Beman Dawes +// Copyright 2001 Dietmar Kuehl +// Copyright 2018-2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // std::bad_alloc, std::nothrow +#include +#include +#include +#include // for malloc, free +#include +#include +#include // for rename + +// Default to POSIX under Emscripten +// If BOOST_FILESYSTEM_EMSCRIPTEN_USE_WASI is set, use WASI instead +#if defined(__wasm) && (!defined(__EMSCRIPTEN__) || defined(BOOST_FILESYSTEM_EMSCRIPTEN_USE_WASI)) +#define BOOST_FILESYSTEM_USE_WASI +#endif + +#ifdef BOOST_POSIX_API + +#include +#include + +#if defined(BOOST_FILESYSTEM_USE_WASI) +// WASI does not have statfs or statvfs. +#elif !defined(__APPLE__) && \ + (!defined(__OpenBSD__) || BOOST_OS_BSD_OPEN >= BOOST_VERSION_NUMBER(4, 4, 0)) && \ + !defined(__ANDROID__) && \ + !defined(__VXWORKS__) +#include +#define BOOST_STATVFS statvfs +#define BOOST_STATVFS_F_FRSIZE vfs.f_frsize +#else +#ifdef __OpenBSD__ +#include +#elif defined(__ANDROID__) +#include +#endif +#if !defined(__VXWORKS__) +#include +#endif +#define BOOST_STATVFS statfs +#define BOOST_STATVFS_F_FRSIZE static_cast< uintmax_t >(vfs.f_bsize) +#endif // BOOST_STATVFS definition + +#include +#include +#if !defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) +#include +#endif +#include + +#if defined(linux) || defined(__linux) || defined(__linux__) + +#include +#include +#include +#include +#if !defined(BOOST_FILESYSTEM_DISABLE_SENDFILE) +#include +#define BOOST_FILESYSTEM_USE_SENDFILE +#endif // !defined(BOOST_FILESYSTEM_DISABLE_SENDFILE) +#if !defined(BOOST_FILESYSTEM_DISABLE_COPY_FILE_RANGE) && defined(__NR_copy_file_range) +#define BOOST_FILESYSTEM_USE_COPY_FILE_RANGE +#endif // !defined(BOOST_FILESYSTEM_DISABLE_COPY_FILE_RANGE) && defined(__NR_copy_file_range) +#if !defined(BOOST_FILESYSTEM_DISABLE_STATX) && (defined(BOOST_FILESYSTEM_HAS_STATX) || defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL)) +#if !defined(BOOST_FILESYSTEM_HAS_STATX) && defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL) +#include +#endif +#define BOOST_FILESYSTEM_USE_STATX +#endif // !defined(BOOST_FILESYSTEM_DISABLE_STATX) && (defined(BOOST_FILESYSTEM_HAS_STATX) || defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL)) + +#if defined(__has_include) +#if __has_include() +// This header was introduced in Linux kernel 2.6.19 +#include +#endif +#endif + +// Some filesystem type magic constants are not defined in older kernel headers +#ifndef PROC_SUPER_MAGIC +#define PROC_SUPER_MAGIC 0x9fa0 +#endif +#ifndef SYSFS_MAGIC +#define SYSFS_MAGIC 0x62656572 +#endif +#ifndef TRACEFS_MAGIC +#define TRACEFS_MAGIC 0x74726163 +#endif +#ifndef DEBUGFS_MAGIC +#define DEBUGFS_MAGIC 0x64626720 +#endif + +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +#if defined(POSIX_FADV_SEQUENTIAL) && (!defined(__ANDROID__) || __ANDROID_API__ >= 21) +#define BOOST_FILESYSTEM_HAS_POSIX_FADVISE +#endif + +#if defined(BOOST_FILESYSTEM_HAS_STAT_ST_MTIM) +#define BOOST_FILESYSTEM_STAT_ST_MTIMENSEC st_mtim.tv_nsec +#elif defined(BOOST_FILESYSTEM_HAS_STAT_ST_MTIMESPEC) +#define BOOST_FILESYSTEM_STAT_ST_MTIMENSEC st_mtimespec.tv_nsec +#elif defined(BOOST_FILESYSTEM_HAS_STAT_ST_MTIMENSEC) +#define BOOST_FILESYSTEM_STAT_ST_MTIMENSEC st_mtimensec +#endif + +#if defined(BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIM) +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIME st_birthtim.tv_sec +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIMENSEC st_birthtim.tv_nsec +#elif defined(BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIMESPEC) +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIME st_birthtimespec.tv_sec +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIMENSEC st_birthtimespec.tv_nsec +#elif defined(BOOST_FILESYSTEM_HAS_STAT_ST_BIRTHTIMENSEC) +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIME st_birthtime +#define BOOST_FILESYSTEM_STAT_ST_BIRTHTIMENSEC st_birthtimensec +#endif + +#include "posix_tools.hpp" + +#else // BOOST_WINDOWS_API + +#include // get_proc_address, GetModuleHandleW +#include +#include +#include +#include +#if defined(__BORLANDC__) || defined(__MWERKS__) +#if defined(BOOST_BORLANDC) +using std::time_t; +#endif +#include +#else +#include +#endif + +#include "windows_tools.hpp" + +#endif // BOOST_WINDOWS_API + +#include "atomic_tools.hpp" +#include "error_handling.hpp" +#include "private_config.hpp" + +#include // must be the last #include + +namespace fs = boost::filesystem; +using boost::filesystem::path; +using boost::filesystem::filesystem_error; +using boost::filesystem::perms; +using boost::system::error_code; +using boost::system::system_category; + +#if defined(BOOST_POSIX_API) + +// At least Mac OS X 10.6 and older doesn't support O_CLOEXEC +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#if defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 +#define BOOST_FILESYSTEM_HAS_FDATASYNC +#endif + +#else // defined(BOOST_POSIX_API) + +#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE +#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) +#endif + +#ifndef FSCTL_GET_REPARSE_POINT +#define FSCTL_GET_REPARSE_POINT 0x900a8 +#endif + +#ifndef SYMLINK_FLAG_RELATIVE +#define SYMLINK_FLAG_RELATIVE 1 +#endif + +// Fallback for MinGW/Cygwin +#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY +#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 +#endif + +#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 +#endif + +#endif // defined(BOOST_POSIX_API) + +// POSIX/Windows macros ----------------------------------------------------// + +// Portions of the POSIX and Windows API's are very similar, except for name, +// order of arguments, and meaning of zero/non-zero returns. The macros below +// abstract away those differences. They follow Windows naming and order of +// arguments, and return true to indicate no error occurred. [POSIX naming, +// order of arguments, and meaning of return were followed initially, but +// found to be less clear and cause more coding errors.] + +#if defined(BOOST_POSIX_API) + +#define BOOST_SET_CURRENT_DIRECTORY(P) (::chdir(P) == 0) +#define BOOST_MOVE_FILE(OLD, NEW) (::rename(OLD, NEW) == 0) +#define BOOST_RESIZE_FILE(P, SZ) (::truncate(P, SZ) == 0) + +#else // BOOST_WINDOWS_API + +#define BOOST_SET_CURRENT_DIRECTORY(P) (::SetCurrentDirectoryW(P) != 0) +#define BOOST_MOVE_FILE(OLD, NEW) (::MoveFileExW(OLD, NEW, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) != 0) +#define BOOST_RESIZE_FILE(P, SZ) (resize_file_impl(P, SZ) != 0) + +#endif + +namespace boost { +namespace filesystem { +namespace detail { + +#if defined(linux) || defined(__linux) || defined(__linux__) +//! Initializes fill_random implementation pointer. Implemented in unique_path.cpp. +void init_fill_random_impl(unsigned int major_ver, unsigned int minor_ver, unsigned int patch_ver); +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) +//! Initializes directory iterator implementation. Implemented in directory.cpp. +void init_directory_iterator_impl() BOOST_NOEXCEPT; +#endif // defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) + +//--------------------------------------------------------------------------------------// +// // +// helpers (all operating systems) // +// // +//--------------------------------------------------------------------------------------// + +namespace { + +// The number of retries remove_all should make if it detects that the directory it is about to enter has been replaced with a symlink or a regular file +BOOST_CONSTEXPR_OR_CONST unsigned int remove_all_directory_replaced_retry_count = 5u; + +#if defined(BOOST_POSIX_API) + +// Size of a small buffer for a path that can be placed on stack, in character code units +BOOST_CONSTEXPR_OR_CONST std::size_t small_path_size = 1024u; + +// Absolute maximum path length, in character code units, that we're willing to accept from various system calls. +// This value is arbitrary, it is supposed to be a hard limit to avoid memory exhaustion +// in some of the algorithms below in case of some corrupted or maliciously broken filesystem. +// A few examples of path size limits: +// - Windows: 32767 UTF-16 code units or 260 bytes for legacy multibyte APIs. +// - Linux: 4096 bytes +// - IRIX, HP-UX, Mac OS, QNX, FreeBSD, OpenBSD: 1024 bytes +// - GNU/Hurd: no hard limit +BOOST_CONSTEXPR_OR_CONST std::size_t absolute_path_max = 32u * 1024u; + +#endif // defined(BOOST_POSIX_API) + +// Maximum number of resolved symlinks before we register a loop +BOOST_CONSTEXPR_OR_CONST unsigned int symloop_max = +#if defined(SYMLOOP_MAX) + SYMLOOP_MAX < 40 ? 40 : SYMLOOP_MAX +#else + 40 +#endif +; + +// general helpers -----------------------------------------------------------------// + +bool is_empty_directory(path const& p, error_code* ec) +{ + fs::directory_iterator itr; + detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::none), NULL, ec); + return itr == fs::directory_iterator(); +} + +bool not_found_error(int errval) BOOST_NOEXCEPT; // forward declaration + +#ifdef BOOST_POSIX_API + +//--------------------------------------------------------------------------------------// +// // +// POSIX-specific helpers // +// // +//--------------------------------------------------------------------------------------// + +struct fd_wrapper +{ + int fd; + + fd_wrapper() BOOST_NOEXCEPT : fd(-1) {} + explicit fd_wrapper(int fd) BOOST_NOEXCEPT : fd(fd) {} + ~fd_wrapper() BOOST_NOEXCEPT + { + if (fd >= 0) + close_fd(fd); + } + BOOST_DELETED_FUNCTION(fd_wrapper(fd_wrapper const&)) + BOOST_DELETED_FUNCTION(fd_wrapper& operator=(fd_wrapper const&)) +}; + +inline bool not_found_error(int errval) BOOST_NOEXCEPT +{ + return errval == ENOENT || errval == ENOTDIR; +} + +#if defined(BOOST_FILESYSTEM_HAS_STATX) + +//! A wrapper for statx libc function. Disable MSAN since at least on clang 10 it doesn't +//! know which fields of struct statx are initialized by the syscall and misdetects errors. +BOOST_FILESYSTEM_NO_SANITIZE_MEMORY +BOOST_FORCEINLINE int invoke_statx(int dirfd, const char* path, int flags, unsigned int mask, struct ::statx* stx) +{ + return ::statx(dirfd, path, flags, mask, stx); +} + +#elif defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL) + +//! statx emulation through fstatat +int statx_fstatat(int dirfd, const char* path, int flags, unsigned int mask, struct ::statx* stx) +{ + struct ::stat st; + flags &= AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW; + int res = ::fstatat(dirfd, path, &st, flags); + if (BOOST_LIKELY(res == 0)) + { + std::memset(stx, 0, sizeof(*stx)); + stx->stx_mask = STATX_BASIC_STATS; + stx->stx_blksize = st.st_blksize; + stx->stx_nlink = st.st_nlink; + stx->stx_uid = st.st_uid; + stx->stx_gid = st.st_gid; + stx->stx_mode = st.st_mode; + stx->stx_ino = st.st_ino; + stx->stx_size = st.st_size; + stx->stx_blocks = st.st_blocks; + stx->stx_atime.tv_sec = st.st_atim.tv_sec; + stx->stx_atime.tv_nsec = st.st_atim.tv_nsec; + stx->stx_ctime.tv_sec = st.st_ctim.tv_sec; + stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec; + stx->stx_mtime.tv_sec = st.st_mtim.tv_sec; + stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec; + stx->stx_rdev_major = major(st.st_rdev); + stx->stx_rdev_minor = minor(st.st_rdev); + stx->stx_dev_major = major(st.st_dev); + stx->stx_dev_minor = minor(st.st_dev); + } + + return res; +} + +typedef int statx_t(int dirfd, const char* path, int flags, unsigned int mask, struct ::statx* stx); + +//! Pointer to the actual implementation of the statx implementation +statx_t* statx_ptr = &statx_fstatat; + +inline int invoke_statx(int dirfd, const char* path, int flags, unsigned int mask, struct ::statx* stx) BOOST_NOEXCEPT +{ + return filesystem::detail::atomic_load_relaxed(statx_ptr)(dirfd, path, flags, mask, stx); +} + +//! A wrapper for the statx syscall. Disable MSAN since at least on clang 10 it doesn't +//! know which fields of struct statx are initialized by the syscall and misdetects errors. +BOOST_FILESYSTEM_NO_SANITIZE_MEMORY +int statx_syscall(int dirfd, const char* path, int flags, unsigned int mask, struct ::statx* stx) +{ + int res = ::syscall(__NR_statx, dirfd, path, flags, mask, stx); + if (res < 0) + { + const int err = errno; + if (BOOST_UNLIKELY(err == ENOSYS)) + { + filesystem::detail::atomic_store_relaxed(statx_ptr, &statx_fstatat); + return statx_fstatat(dirfd, path, flags, mask, stx); + } + } + + return res; +} + +#endif // defined(BOOST_FILESYSTEM_HAS_STATX) + +#if defined(linux) || defined(__linux) || defined(__linux__) + +//! Initializes statx implementation pointer +inline void init_statx_impl(unsigned int major_ver, unsigned int minor_ver, unsigned int patch_ver) +{ +#if !defined(BOOST_FILESYSTEM_HAS_STATX) && defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL) + statx_t* stx = &statx_fstatat; + if (major_ver > 4u || (major_ver == 4u && minor_ver >= 11u)) + stx = &statx_syscall; + + filesystem::detail::atomic_store_relaxed(statx_ptr, stx); +#endif // !defined(BOOST_FILESYSTEM_HAS_STATX) && defined(BOOST_FILESYSTEM_HAS_STATX_SYSCALL) +} + +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + +//! Returns \c true if the two \c statx structures refer to the same file +inline bool equivalent_stat(struct ::statx const& s1, struct ::statx const& s2) BOOST_NOEXCEPT +{ + return s1.stx_dev_major == s2.stx_dev_major && s1.stx_dev_minor == s2.stx_dev_minor && s1.stx_ino == s2.stx_ino; +} + +//! Returns file type/access mode from \c statx structure +inline mode_t get_mode(struct ::statx const& st) BOOST_NOEXCEPT +{ + return st.stx_mode; +} + +//! Returns file size from \c statx structure +inline uintmax_t get_size(struct ::statx const& st) BOOST_NOEXCEPT +{ + return st.stx_size; +} + +//! Returns optimal block size from \c statx structure +inline std::size_t get_blksize(struct ::statx const& st) BOOST_NOEXCEPT +{ + return st.stx_blksize; +} + +#else // defined(BOOST_FILESYSTEM_USE_STATX) + +//! Returns \c true if the two \c stat structures refer to the same file +inline bool equivalent_stat(struct ::stat const& s1, struct ::stat const& s2) BOOST_NOEXCEPT +{ + // According to the POSIX stat specs, "The st_ino and st_dev fields + // taken together uniquely identify the file within the system." + return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino; +} + +//! Returns file type/access mode from \c stat structure +inline mode_t get_mode(struct ::stat const& st) BOOST_NOEXCEPT +{ + return st.st_mode; +} + +//! Returns file size from \c stat structure +inline uintmax_t get_size(struct ::stat const& st) BOOST_NOEXCEPT +{ + return st.st_size; +} + +//! Returns optimal block size from \c stat structure +inline std::size_t get_blksize(struct ::stat const& st) BOOST_NOEXCEPT +{ +#if defined(BOOST_FILESYSTEM_HAS_STAT_ST_BLKSIZE) + return st.st_blksize; +#else + return 4096u; // a suitable default used on most modern SSDs/HDDs +#endif +} + +#endif // defined(BOOST_FILESYSTEM_USE_STATX) + +//! status() implementation +file_status status_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +) +{ +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + int err = invoke_statx(basedir_fd, p.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); +#elif defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + struct ::stat path_stat; + int err = ::fstatat(basedir_fd, p.c_str(), &path_stat, AT_NO_AUTOMOUNT); +#else + struct ::stat path_stat; + int err = ::stat(p.c_str(), &path_stat); +#endif + + if (err != 0) + { + err = errno; + if (ec) // always report errno, even though some + ec->assign(err, system_category()); // errno values are not status_errors + + if (not_found_error(err)) + return fs::file_status(fs::file_not_found, fs::no_perms); + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, error_code(err, system_category()))); + + return fs::file_status(fs::status_error); + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::status"); + return fs::file_status(fs::status_error); + } +#endif + + const mode_t mode = get_mode(path_stat); + if (S_ISDIR(mode)) + return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISREG(mode)) + return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISBLK(mode)) + return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISCHR(mode)) + return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISFIFO(mode)) + return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISSOCK(mode)) + return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); + + return fs::file_status(fs::type_unknown); +} + +//! symlink_status() implementation +file_status symlink_status_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +) +{ +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + int err = invoke_statx(basedir_fd, p.c_str(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); +#elif defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + struct ::stat path_stat; + int err = ::fstatat(basedir_fd, p.c_str(), &path_stat, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT); +#else + struct ::stat path_stat; + int err = ::lstat(p.c_str(), &path_stat); +#endif + + if (err != 0) + { + err = errno; + if (ec) // always report errno, even though some + ec->assign(err, system_category()); // errno values are not status_errors + + if (not_found_error(err)) // these are not errors + return fs::file_status(fs::file_not_found, fs::no_perms); + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::symlink_status", p, error_code(err, system_category()))); + + return fs::file_status(fs::status_error); + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::symlink_status"); + return fs::file_status(fs::status_error); + } +#endif + + const mode_t mode = get_mode(path_stat); + if (S_ISREG(mode)) + return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISDIR(mode)) + return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISLNK(mode)) + return fs::file_status(fs::symlink_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISBLK(mode)) + return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISCHR(mode)) + return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISFIFO(mode)) + return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISSOCK(mode)) + return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); + + return fs::file_status(fs::type_unknown); +} + +//! Flushes buffered data and attributes written to the file to permanent storage +inline int full_sync(int fd) +{ + while (true) + { +#if defined(__APPLE__) && defined(__MACH__) && defined(F_FULLFSYNC) + // Mac OS does not flush data to physical storage with fsync() + int err = ::fcntl(fd, F_FULLFSYNC); +#else + int err = ::fsync(fd); +#endif + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + // POSIX says fsync can return EINTR (https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html). + // fcntl(F_FULLFSYNC) isn't documented to return EINTR, but it doesn't hurt to check. + if (err == EINTR) + continue; + + return err; + } + + break; + } + + return 0; +} + +//! Flushes buffered data written to the file to permanent storage +inline int data_sync(int fd) +{ +#if defined(BOOST_FILESYSTEM_HAS_FDATASYNC) && !(defined(__APPLE__) && defined(__MACH__) && defined(F_FULLFSYNC)) + while (true) + { + int err = ::fdatasync(fd); + if (BOOST_UNLIKELY(err != 0)) + { + err = errno; + // POSIX says fsync can return EINTR (https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html). + // It doesn't say so for fdatasync, but it is reasonable to expect it as well. + if (err == EINTR) + continue; + + return err; + } + + break; + } + + return 0; +#else + return full_sync(fd); +#endif +} + +// Min and max buffer sizes are selected to minimize the overhead from system calls. +// The values are picked based on coreutils cp(1) benchmarking data described here: +// https://github.com/coreutils/coreutils/blob/d1b0257077c0b0f0ee25087efd46270345d1dd1f/src/ioblksize.h#L23-L72 +BOOST_CONSTEXPR_OR_CONST uint_least32_t min_read_write_buf_size = 8u * 1024u; +BOOST_CONSTEXPR_OR_CONST uint_least32_t max_read_write_buf_size = 256u * 1024u; + +//! copy_file read/write loop implementation +int copy_file_data_read_write_impl(int infile, int outfile, char* buf, std::size_t buf_size) +{ +#if defined(BOOST_FILESYSTEM_HAS_POSIX_FADVISE) + ::posix_fadvise(infile, 0, 0, POSIX_FADV_SEQUENTIAL); +#endif + + // Don't use file size to limit the amount of data to copy since some filesystems, like procfs or sysfs, + // provide files with generated content and indicate that their size is zero or 4096. Just copy as much data + // as we can read from the input file. + while (true) + { + ssize_t sz_read = ::read(infile, buf, buf_size); + if (sz_read == 0) + break; + if (BOOST_UNLIKELY(sz_read < 0)) + { + int err = errno; + if (err == EINTR) + continue; + return err; + } + + // Allow for partial writes - see Advanced Unix Programming (2nd Ed.), + // Marc Rochkind, Addison-Wesley, 2004, page 94 + for (ssize_t sz_wrote = 0; sz_wrote < sz_read;) + { + ssize_t sz = ::write(outfile, buf + sz_wrote, static_cast< std::size_t >(sz_read - sz_wrote)); + if (BOOST_UNLIKELY(sz < 0)) + { + int err = errno; + if (err == EINTR) + continue; + return err; + } + + sz_wrote += sz; + } + } + + return 0; +} + +//! copy_file implementation that uses read/write loop (fallback using a stack buffer) +int copy_file_data_read_write_stack_buf(int infile, int outfile) +{ + char stack_buf[min_read_write_buf_size]; + return copy_file_data_read_write_impl(infile, outfile, stack_buf, sizeof(stack_buf)); +} + +//! copy_file implementation that uses read/write loop +int copy_file_data_read_write(int infile, int outfile, uintmax_t size, std::size_t blksize) +{ + { + uintmax_t buf_sz = size; + // Prefer the buffer to be larger than the file size so that we don't have + // to perform an extra read if the file fits in the buffer exactly. + buf_sz += (buf_sz < ~static_cast< uintmax_t >(0u)); + if (buf_sz < blksize) + buf_sz = blksize; + if (buf_sz < min_read_write_buf_size) + buf_sz = min_read_write_buf_size; + if (buf_sz > max_read_write_buf_size) + buf_sz = max_read_write_buf_size; + const std::size_t buf_size = static_cast< std::size_t >(boost::core::bit_ceil(static_cast< uint_least32_t >(buf_sz))); + boost::scoped_array< char > buf(new (std::nothrow) char[buf_size]); + if (BOOST_LIKELY(!!buf.get())) + return copy_file_data_read_write_impl(infile, outfile, buf.get(), buf_size); + } + + return copy_file_data_read_write_stack_buf(infile, outfile); +} + +typedef int copy_file_data_t(int infile, int outfile, uintmax_t size, std::size_t blksize); + +//! Pointer to the actual implementation of the copy_file_data implementation +copy_file_data_t* copy_file_data = ©_file_data_read_write; + +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +//! copy_file_data wrapper that tests if a read/write loop must be used for a given filesystem +template< typename CopyFileData > +int check_fs_type(int infile, int outfile, uintmax_t size, std::size_t blksize); + +#endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) + +struct copy_file_data_sendfile +{ + //! copy_file implementation that uses sendfile loop. Requires sendfile to support file descriptors. + static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize) + { + // sendfile will not send more than this amount of data in one call + BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; + uintmax_t offset = 0u; + while (offset < size) + { + uintmax_t size_left = size - offset; + std::size_t size_to_copy = max_batch_size; + if (size_left < static_cast< uintmax_t >(max_batch_size)) + size_to_copy = static_cast< std::size_t >(size_left); + ssize_t sz = ::sendfile(outfile, infile, NULL, size_to_copy); + if (BOOST_UNLIKELY(sz < 0)) + { + int err = errno; + if (err == EINTR) + continue; + + if (offset == 0u) + { + // sendfile may fail with EINVAL if the underlying filesystem does not support it + if (err == EINVAL) + { + fallback_to_read_write: + return copy_file_data_read_write(infile, outfile, size, blksize); + } + + if (err == ENOSYS) + { + filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); + goto fallback_to_read_write; + } + } + + return err; + } + + offset += sz; + } + + return 0; + } +}; + +#endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) + +#if defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +struct copy_file_data_copy_file_range +{ + //! copy_file implementation that uses copy_file_range loop. Requires copy_file_range to support cross-filesystem copying. + static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize) + { + // Although copy_file_range does not document any particular upper limit of one transfer, still use some upper bound to guarantee + // that size_t is not overflown in case if off_t is larger and the file size does not fit in size_t. + BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; + uintmax_t offset = 0u; + while (offset < size) + { + uintmax_t size_left = size - offset; + std::size_t size_to_copy = max_batch_size; + if (size_left < static_cast< uintmax_t >(max_batch_size)) + size_to_copy = static_cast< std::size_t >(size_left); + // Note: Use syscall directly to avoid depending on libc version. copy_file_range is added in glibc 2.27. + // uClibc-ng does not have copy_file_range as of the time of this writing (the latest uClibc-ng release is 1.0.33). + loff_t sz = ::syscall(__NR_copy_file_range, infile, (loff_t*)NULL, outfile, (loff_t*)NULL, size_to_copy, (unsigned int)0u); + if (BOOST_UNLIKELY(sz < 0)) + { + int err = errno; + if (err == EINTR) + continue; + + if (offset == 0u) + { + // copy_file_range may fail with EINVAL if the underlying filesystem does not support it. + // In some RHEL/CentOS 7.7-7.8 kernel versions, copy_file_range on NFSv4 is also known to return EOPNOTSUPP + // if the remote server does not support COPY, despite that it is not a documented error code. + // See https://patchwork.kernel.org/project/linux-nfs/patch/20190411183418.4510-1-olga.kornievskaia@gmail.com/ + // and https://bugzilla.redhat.com/show_bug.cgi?id=1783554. + if (err == EINVAL || err == EOPNOTSUPP) + { +#if !defined(BOOST_FILESYSTEM_USE_SENDFILE) + fallback_to_read_write: +#endif + return copy_file_data_read_write(infile, outfile, size, blksize); + } + + if (err == EXDEV) + { +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) + fallback_to_sendfile: + return copy_file_data_sendfile::impl(infile, outfile, size, blksize); +#else + goto fallback_to_read_write; +#endif + } + + if (err == ENOSYS) + { +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) + filesystem::detail::atomic_store_relaxed(copy_file_data, &check_fs_type< copy_file_data_sendfile >); + goto fallback_to_sendfile; +#else + filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); + goto fallback_to_read_write; +#endif + } + } + + return err; + } + + offset += sz; + } + + return 0; + } +}; + +#endif // defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +//! copy_file_data wrapper that tests if a read/write loop must be used for a given filesystem +template< typename CopyFileData > +int check_fs_type(int infile, int outfile, uintmax_t size, std::size_t blksize) +{ + { + // Some filesystems have regular files with generated content. Such files have arbitrary size, including zero, + // but have actual content. Linux system calls sendfile or copy_file_range will not copy contents of such files, + // so we must use a read/write loop to handle them. + // https://lore.kernel.org/linux-fsdevel/20210212044405.4120619-1-drinkcat@chromium.org/T/ + struct statfs sfs; + while (true) + { + int err = ::fstatfs(infile, &sfs); + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + if (err == EINTR) + continue; + + goto fallback_to_read_write; + } + + break; + } + + if (BOOST_UNLIKELY(sfs.f_type == PROC_SUPER_MAGIC || + sfs.f_type == SYSFS_MAGIC || + sfs.f_type == TRACEFS_MAGIC || + sfs.f_type == DEBUGFS_MAGIC)) + { + fallback_to_read_write: + return copy_file_data_read_write(infile, outfile, size, blksize); + } + } + + return CopyFileData::impl(infile, outfile, size, blksize); +} + +#endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +#if defined(linux) || defined(__linux) || defined(__linux__) + +//! Initializes copy_file_data implementation pointer +inline void init_copy_file_data_impl(unsigned int major_ver, unsigned int minor_ver, unsigned int patch_ver) +{ +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + copy_file_data_t* cfd = ©_file_data_read_write; + +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) + // sendfile started accepting file descriptors as the target in Linux 2.6.33 + if (major_ver > 2u || (major_ver == 2u && (minor_ver > 6u || (minor_ver == 6u && patch_ver >= 33u)))) + cfd = &check_fs_type< copy_file_data_sendfile >; +#endif + +#if defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + // Although copy_file_range appeared in Linux 4.5, it did not support cross-filesystem copying until 5.3. + // copy_file_data_copy_file_range will fallback to copy_file_data_sendfile if copy_file_range returns EXDEV. + if (major_ver > 4u || (major_ver == 4u && minor_ver >= 5u)) + cfd = &check_fs_type< copy_file_data_copy_file_range >; +#endif + + filesystem::detail::atomic_store_relaxed(copy_file_data, cfd); +#endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) +} + +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +#if defined(linux) || defined(__linux) || defined(__linux__) + +struct syscall_initializer +{ + syscall_initializer() + { + struct ::utsname system_info; + if (BOOST_UNLIKELY(::uname(&system_info) < 0)) + return; + + unsigned int major_ver = 0u, minor_ver = 0u, patch_ver = 0u; + int count = std::sscanf(system_info.release, "%u.%u.%u", &major_ver, &minor_ver, &patch_ver); + if (BOOST_UNLIKELY(count < 3)) + return; + + init_statx_impl(major_ver, minor_ver, patch_ver); + init_copy_file_data_impl(major_ver, minor_ver, patch_ver); + init_fill_random_impl(major_ver, minor_ver, patch_ver); + } +}; + +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_FUNC_PTR_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +const syscall_initializer syscall_init; + +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +//! remove() implementation +inline bool remove_impl +( + path const& p, + fs::file_type type, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , int basedir_fd = AT_FDCWD +#endif +) +{ + if (type == fs::file_not_found) + return false; + + int res; +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + res = ::unlinkat(basedir_fd, p.c_str(), type == fs::directory_file ? AT_REMOVEDIR : 0); +#else + if (type == fs::directory_file) + res = ::rmdir(p.c_str()); + else + res = ::unlink(p.c_str()); +#endif + + if (res != 0) + { + int err = errno; + if (BOOST_UNLIKELY(!not_found_error(err))) + emit_error(err, p, ec, "boost::filesystem::remove"); + + return false; + } + + return true; +} + +//! remove() implementation +inline bool remove_impl(path const& p, error_code* ec) +{ + // Since POSIX remove() is specified to work with either files or directories, in a + // perfect world it could just be called. But some important real-world operating + // systems (Windows, Mac OS, for example) don't implement the POSIX spec. So + // we have to distinguish between files and directories and call corresponding APIs + // to remove them. + + error_code local_ec; + fs::file_type type = fs::detail::symlink_status_impl(p, &local_ec).type(); + if (BOOST_UNLIKELY(type == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove", p, local_ec)); + + *ec = local_ec; + return false; + } + + return fs::detail::remove_impl(p, type, ec); +} + +//! remove_all() implementation +uintmax_t remove_all_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , int basedir_fd = AT_FDCWD +#endif +) +{ +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + fs::detail::directory_iterator_params params; + params.basedir_fd = basedir_fd; + params.iterator_fd = -1; +#endif + + error_code dit_create_ec; + for (unsigned int attempt = 0u; attempt < remove_all_directory_replaced_retry_count; ++attempt) + { + fs::file_type type; + { + error_code local_ec; + type = fs::detail::symlink_status_impl + ( + p, + &local_ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , basedir_fd +#endif + ).type(); + + if (type == fs::file_not_found) + return 0u; + + if (BOOST_UNLIKELY(type == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, local_ec)); + + *ec = local_ec; + return static_cast< uintmax_t >(-1); + } + } + + uintmax_t count = 0u; + if (type == fs::directory_file) // but not a directory symlink + { + fs::directory_iterator itr; + fs::detail::directory_iterator_construct + ( + itr, + p, + static_cast< unsigned int >(directory_options::_detail_no_follow), +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + ¶ms, +#else + NULL, +#endif + &dit_create_ec + ); + + if (BOOST_UNLIKELY(!!dit_create_ec)) + { + if (dit_create_ec == error_code(ENOTDIR, system_category())) + continue; + +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + // If open(2) with O_NOFOLLOW fails with ELOOP, this means that either the path contains a loop + // of symbolic links, or the last element of the path is a symbolic link. Given that lstat(2) above + // did not fail, most likely it is the latter case. I.e. between the lstat above and this open call + // the filesystem was modified so that the path no longer refers to a directory file (as opposed to a symlink). + if (dit_create_ec == error_code(ELOOP, system_category())) + continue; +#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, dit_create_ec)); + + *ec = dit_create_ec; + return static_cast< uintmax_t >(-1); + } + + const fs::directory_iterator end_dit; + while (itr != end_dit) + { + count += fs::detail::remove_all_impl + ( +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + path_algorithms::filename_v4(itr->path()), +#else + itr->path(), +#endif + ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , params.iterator_fd +#endif + ); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + fs::detail::directory_iterator_increment(itr, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + } + } + + count += fs::detail::remove_impl + ( + p, + type, + ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , basedir_fd +#endif + ); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + return count; + } + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all: path cannot be opened as a directory", p, dit_create_ec)); + + *ec = dit_create_ec; + return static_cast< uintmax_t >(-1); +} + +#else // defined(BOOST_POSIX_API) + +//--------------------------------------------------------------------------------------// +// // +// Windows-specific helpers // +// // +//--------------------------------------------------------------------------------------// + +//! FILE_BASIC_INFO definition from Windows SDK +struct file_basic_info +{ + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + DWORD FileAttributes; +}; + +//! FILE_DISPOSITION_INFO definition from Windows SDK +struct file_disposition_info +{ + BOOLEAN DeleteFile; +}; + +//! FILE_DISPOSITION_INFO_EX definition from Windows SDK +struct file_disposition_info_ex +{ + DWORD Flags; +}; + +#ifndef FILE_DISPOSITION_FLAG_DELETE +#define FILE_DISPOSITION_FLAG_DELETE 0x00000001 +#endif +// Available since Windows 10 1709 +#ifndef FILE_DISPOSITION_FLAG_POSIX_SEMANTICS +#define FILE_DISPOSITION_FLAG_POSIX_SEMANTICS 0x00000002 +#endif +// Available since Windows 10 1809 +#ifndef FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE +#define FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE 0x00000010 +#endif + +// REPARSE_DATA_BUFFER related definitions are found in ntifs.h, which is part of the +// Windows Device Driver Kit. Since that's inconvenient, the definitions are provided +// here. See http://msdn.microsoft.com/en-us/library/ms791514.aspx +struct reparse_data_buffer +{ + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union + { + /* + * In SymbolicLink and MountPoint reparse points, there are two names. + * SubstituteName is the effective replacement path for the reparse point. + * This is what should be used for path traversal. + * PrintName is intended for presentation to the user and may omit some + * elements of the path or be absent entirely. + * + * Examples of substitute and print names: + * mklink /D ldrive c:\ + * SubstituteName: "\??\c:\" + * PrintName: "c:\" + * + * mklink /J ldrive c:\ + * SubstituteName: "\??\C:\" + * PrintName: "c:\" + * + * junction ldrive c:\ + * SubstituteName: "\??\C:\" + * PrintName: "" + * + * box.com mounted cloud storage + * SubstituteName: "\??\Volume{}\" + * PrintName: "" + */ + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct + { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +}; + +// Our convenience type for allocating REPARSE_DATA_BUFFER along with sufficient space after it +union reparse_data_buffer_with_storage +{ + reparse_data_buffer rdb; + unsigned char storage[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; +}; + +// Windows kernel32.dll functions that may or may not be present +// must be accessed through pointers + +typedef BOOL (WINAPI CreateHardLinkW_t)( + /*__in*/ LPCWSTR lpFileName, + /*__in*/ LPCWSTR lpExistingFileName, + /*__reserved*/ LPSECURITY_ATTRIBUTES lpSecurityAttributes); + +CreateHardLinkW_t* create_hard_link_api = NULL; + +typedef BOOLEAN (WINAPI CreateSymbolicLinkW_t)( + /*__in*/ LPCWSTR lpSymlinkFileName, + /*__in*/ LPCWSTR lpTargetFileName, + /*__in*/ DWORD dwFlags); + +CreateSymbolicLinkW_t* create_symbolic_link_api = NULL; + +//! SetFileInformationByHandle signature. Available since Windows Vista. +typedef BOOL (WINAPI SetFileInformationByHandle_t)( + /*_In_*/ HANDLE hFile, + /*_In_*/ file_info_by_handle_class FileInformationClass, // the actual type is FILE_INFO_BY_HANDLE_CLASS enum + /*_In_reads_bytes_(dwBufferSize)*/ LPVOID lpFileInformation, + /*_In_*/ DWORD dwBufferSize); + +SetFileInformationByHandle_t* set_file_information_by_handle_api = NULL; + +} // unnamed namespace + +GetFileInformationByHandleEx_t* get_file_information_by_handle_ex_api = NULL; + +#if !defined(UNDER_CE) +NtCreateFile_t* nt_create_file_api = NULL; +NtQueryDirectoryFile_t* nt_query_directory_file_api = NULL; +#endif // !defined(UNDER_CE) + +namespace { + +//! remove() implementation type +enum remove_impl_type +{ + remove_nt5, //!< Use Windows XP API + remove_disp, //!< Use FILE_DISPOSITION_INFO (Windows Vista and later) + remove_disp_ex_flag_posix_semantics, //!< Use FILE_DISPOSITION_INFO_EX with FILE_DISPOSITION_FLAG_POSIX_SEMANTICS + remove_disp_ex_flag_ignore_readonly //!< Use FILE_DISPOSITION_INFO_EX with FILE_DISPOSITION_FLAG_POSIX_SEMANTICS | FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE +}; + +remove_impl_type g_remove_impl_type = remove_nt5; + +//! Initializes WinAPI function pointers +BOOST_FILESYSTEM_INIT_FUNC init_winapi_func_ptrs() +{ + boost::winapi::HMODULE_ h = boost::winapi::GetModuleHandleW(L"kernel32.dll"); + if (BOOST_LIKELY(!!h)) + { + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = (GetFileInformationByHandleEx_t*)boost::winapi::get_proc_address(h, "GetFileInformationByHandleEx"); + filesystem::detail::atomic_store_relaxed(get_file_information_by_handle_ex_api, get_file_information_by_handle_ex); + SetFileInformationByHandle_t* set_file_information_by_handle = (SetFileInformationByHandle_t*)boost::winapi::get_proc_address(h, "SetFileInformationByHandle"); + filesystem::detail::atomic_store_relaxed(set_file_information_by_handle_api, set_file_information_by_handle); + filesystem::detail::atomic_store_relaxed(create_hard_link_api, (CreateHardLinkW_t*)boost::winapi::get_proc_address(h, "CreateHardLinkW")); + filesystem::detail::atomic_store_relaxed(create_symbolic_link_api, (CreateSymbolicLinkW_t*)boost::winapi::get_proc_address(h, "CreateSymbolicLinkW")); + + if (get_file_information_by_handle_ex && set_file_information_by_handle) + { + // Enable the most advanced implementation based on GetFileInformationByHandleEx/SetFileInformationByHandle. + // If certain flags are not supported by the OS, the remove() implementation will downgrade accordingly. + filesystem::detail::atomic_store_relaxed(g_remove_impl_type, remove_disp_ex_flag_ignore_readonly); + } + } + +#if !defined(UNDER_CE) + h = boost::winapi::GetModuleHandleW(L"ntdll.dll"); + if (BOOST_LIKELY(!!h)) + { + filesystem::detail::atomic_store_relaxed(nt_create_file_api, (NtCreateFile_t*)boost::winapi::get_proc_address(h, "NtCreateFile")); + filesystem::detail::atomic_store_relaxed(nt_query_directory_file_api, (NtQueryDirectoryFile_t*)boost::winapi::get_proc_address(h, "NtQueryDirectoryFile")); + } + + init_directory_iterator_impl(); +#endif // !defined(UNDER_CE) + + return BOOST_FILESYSTEM_INITRETSUCCESS_V; +} + +#if defined(_MSC_VER) + +#if _MSC_VER >= 1400 + +#pragma section(".CRT$XCL", long, read) +__declspec(allocate(".CRT$XCL")) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +extern const init_func_ptr_t p_init_winapi_func_ptrs = &init_winapi_func_ptrs; + +#else // _MSC_VER >= 1400 + +#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +#pragma data_seg(push, old_seg) +#endif +#pragma data_seg(".CRT$XCL") +BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +extern const init_func_ptr_t p_init_winapi_func_ptrs = &init_winapi_func_ptrs; +#pragma data_seg() +#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +#pragma data_seg(pop, old_seg) +#endif + +#endif // _MSC_VER >= 1400 + +#if defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN) +//! Makes sure the global initializer pointers are referenced and not removed by linker +struct globals_retainer +{ + const init_func_ptr_t* volatile m_p_init_winapi_func_ptrs; + + globals_retainer() { m_p_init_winapi_func_ptrs = &p_init_winapi_func_ptrs; } +}; +BOOST_ATTRIBUTE_UNUSED +const globals_retainer g_globals_retainer; +#endif // defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN) + +#else // defined(_MSC_VER) + +//! Invokes WinAPI function pointers initialization +struct winapi_func_ptrs_initializer +{ + winapi_func_ptrs_initializer() { init_winapi_func_ptrs(); } +}; + +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_FUNC_PTR_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +const winapi_func_ptrs_initializer winapi_func_ptrs_init; + +#endif // defined(_MSC_VER) + + +// Windows CE has no environment variables +#if !defined(UNDER_CE) +inline std::wstring wgetenv(const wchar_t* name) +{ + // use a separate buffer since C++03 basic_string is not required to be contiguous + const DWORD size = ::GetEnvironmentVariableW(name, NULL, 0); + if (size > 0) + { + boost::scoped_array< wchar_t > buf(new wchar_t[size]); + if (BOOST_LIKELY(::GetEnvironmentVariableW(name, buf.get(), size) > 0)) + return std::wstring(buf.get()); + } + + return std::wstring(); +} +#endif // !defined(UNDER_CE) + +inline bool not_found_error(int errval) BOOST_NOEXCEPT +{ + return errval == ERROR_FILE_NOT_FOUND || errval == ERROR_PATH_NOT_FOUND || errval == ERROR_INVALID_NAME // "tools/jam/src/:sys:stat.h", "//foo" + || errval == ERROR_INVALID_DRIVE // USB card reader with no card inserted + || errval == ERROR_NOT_READY // CD/DVD drive with no disc inserted + || errval == ERROR_INVALID_PARAMETER // ":sys:stat.h" + || errval == ERROR_BAD_PATHNAME // "//no-host" on Win64 + || errval == ERROR_BAD_NETPATH // "//no-host" on Win32 + || errval == ERROR_BAD_NET_NAME; // "//no-host/no-share" on Win10 x64 +} + +// these constants come from inspecting some Microsoft sample code +inline std::time_t to_time_t(FILETIME const& ft) BOOST_NOEXCEPT +{ + uint64_t t = (static_cast< uint64_t >(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + t -= 116444736000000000ull; + t /= 10000000u; + return static_cast< std::time_t >(t); +} + +inline void to_FILETIME(std::time_t t, FILETIME& ft) BOOST_NOEXCEPT +{ + uint64_t temp = t; + temp *= 10000000u; + temp += 116444736000000000ull; + ft.dwLowDateTime = static_cast< DWORD >(temp); + ft.dwHighDateTime = static_cast< DWORD >(temp >> 32); +} + +} // unnamed namespace + +#if !defined(UNDER_CE) + +//! The flag indicates whether OBJ_DONT_REPARSE flag is not supported by the kernel +static bool g_no_obj_dont_reparse = false; + +//! Creates a file handle for a file relative to a previously opened base directory. The file path must be relative and in preferred format. +boost::winapi::NTSTATUS_ nt_create_file_handle_at(HANDLE& out, HANDLE basedir_handle, boost::filesystem::path const& p, ULONG FileAttributes, ACCESS_MASK DesiredAccess, ULONG ShareMode, ULONG CreateDisposition, ULONG CreateOptions) +{ + NtCreateFile_t* nt_create_file = filesystem::detail::atomic_load_relaxed(nt_create_file_api); + if (BOOST_UNLIKELY(!nt_create_file)) + return STATUS_NOT_IMPLEMENTED; + + unicode_string obj_name = {}; + obj_name.Buffer = const_cast< wchar_t* >(p.c_str()); + obj_name.Length = obj_name.MaximumLength = static_cast< USHORT >(p.size() * sizeof(wchar_t)); + + object_attributes obj_attrs = {}; + obj_attrs.Length = sizeof(obj_attrs); + obj_attrs.RootDirectory = basedir_handle; + obj_attrs.ObjectName = &obj_name; + + obj_attrs.Attributes = OBJ_CASE_INSENSITIVE; + if ((CreateOptions & FILE_OPEN_REPARSE_POINT) != 0u && !filesystem::detail::atomic_load_relaxed(g_no_obj_dont_reparse)) + obj_attrs.Attributes |= OBJ_DONT_REPARSE; + + io_status_block iosb; + boost::winapi::NTSTATUS_ status = nt_create_file + ( + &out, + DesiredAccess, + &obj_attrs, + &iosb, + NULL, // AllocationSize + FileAttributes, + ShareMode, + CreateDisposition, + CreateOptions, + NULL, // EaBuffer + 0u // EaLength + ); + + if (BOOST_UNLIKELY(status == STATUS_INVALID_PARAMETER && (obj_attrs.Attributes & OBJ_DONT_REPARSE) != 0u)) + { + // OBJ_DONT_REPARSE is supported since Windows 10, retry without it + filesystem::detail::atomic_store_relaxed(g_no_obj_dont_reparse, true); + obj_attrs.Attributes &= ~static_cast< ULONG >(OBJ_DONT_REPARSE); + + status = nt_create_file + ( + &out, + DesiredAccess, + &obj_attrs, + &iosb, + NULL, // AllocationSize + FileAttributes, + ShareMode, + CreateDisposition, + CreateOptions, + NULL, // EaBuffer + 0u // EaLength + ); + } + + return status; +} + +#endif // !defined(UNDER_CE) + +ULONG get_reparse_point_tag_ioctl(HANDLE h, path const& p, error_code* ec) +{ + boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new (std::nothrow) reparse_data_buffer_with_storage); + if (BOOST_UNLIKELY(!buf.get())) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("Cannot allocate memory to query reparse point", p, make_error_code(system::errc::not_enough_memory))); + + *ec = make_error_code(system::errc::not_enough_memory); + return 0u; + } + + // Query the reparse data + DWORD dwRetLen = 0u; + BOOL result = ::DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), sizeof(*buf), &dwRetLen, NULL); + if (BOOST_UNLIKELY(!result)) + { + DWORD err = ::GetLastError(); + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("Failed to query reparse point", p, error_code(err, system_category()))); + + ec->assign(err, system_category()); + return 0u; + } + + return buf->rdb.ReparseTag; +} + +namespace { + +inline std::size_t get_full_path_name(path const& src, std::size_t len, wchar_t* buf, wchar_t** p) +{ + return static_cast< std::size_t >(::GetFullPathNameW(src.c_str(), static_cast< DWORD >(len), buf, p)); +} + +inline fs::file_status process_status_failure(DWORD errval, path const& p, error_code* ec) +{ + if (ec) // always report errval, even though some + ec->assign(errval, system_category()); // errval values are not status_errors + + if (not_found_error(errval)) + { + return fs::file_status(fs::file_not_found, fs::no_perms); + } + else if (errval == ERROR_SHARING_VIOLATION) + { + return fs::file_status(fs::type_unknown); + } + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, error_code(errval, system_category()))); + + return fs::file_status(fs::status_error); +} + +inline fs::file_status process_status_failure(path const& p, error_code* ec) +{ + return process_status_failure(::GetLastError(), p, ec); +} + +//! (symlink_)status() by handle implementation +fs::file_status status_by_handle(HANDLE h, path const& p, error_code* ec) +{ + fs::file_type ftype; + DWORD attrs; + ULONG reparse_tag = 0u; + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); + if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) + { + file_attribute_tag_info info; + BOOL res = get_file_information_by_handle_ex(h, file_attribute_tag_info_class, &info, sizeof(info)); + if (BOOST_UNLIKELY(!res)) + { + // On FAT/exFAT filesystems requesting FILE_ATTRIBUTE_TAG_INFO returns ERROR_INVALID_PARAMETER. + // Presumably, this is because these filesystems don't support reparse points, so ReparseTag + // cannot be returned. Also check ERROR_NOT_SUPPORTED for good measure. Fall back to the legacy + // code path in this case. + DWORD err = ::GetLastError(); + if (err == ERROR_INVALID_PARAMETER || err == ERROR_NOT_SUPPORTED) + goto use_get_file_information_by_handle; + + return process_status_failure(err, p, ec); + } + + attrs = info.FileAttributes; + reparse_tag = info.ReparseTag; + } + else + { + use_get_file_information_by_handle: + BY_HANDLE_FILE_INFORMATION info; + BOOL res = ::GetFileInformationByHandle(h, &info); + if (BOOST_UNLIKELY(!res)) + return process_status_failure(p, ec); + + attrs = info.dwFileAttributes; + + if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0u) + { + reparse_tag = get_reparse_point_tag_ioctl(h, p, ec); + if (ec) + { + if (BOOST_UNLIKELY(!!ec)) + return fs::file_status(fs::status_error); + } + } + } + + if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0u) + { + if (reparse_tag == IO_REPARSE_TAG_DEDUP) + ftype = fs::regular_file; + else if (is_reparse_point_tag_a_symlink(reparse_tag)) + ftype = fs::symlink_file; + else + ftype = fs::reparse_file; + } + else if ((attrs & FILE_ATTRIBUTE_DIRECTORY) != 0u) + { + ftype = fs::directory_file; + } + else + { + ftype = fs::regular_file; + } + + return fs::file_status(ftype, make_permissions(p, attrs)); +} + +//! symlink_status() implementation +fs::file_status symlink_status_impl(path const& p, error_code* ec) +{ + // Normally, we only need FILE_READ_ATTRIBUTES access mode. But SMBv1 reports incorrect + // file attributes in GetFileInformationByHandleEx in this case (e.g. it reports FILE_ATTRIBUTE_NORMAL + // for a directory in a SMBv1 share), so we add FILE_READ_EA as a workaround. + // https://github.com/boostorg/filesystem/issues/282 + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, // lpSecurityAttributes + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + + if (h.handle == INVALID_HANDLE_VALUE) + { + // For some system files and folders like "System Volume Information" CreateFileW fails + // with ERROR_ACCESS_DENIED. GetFileAttributesW succeeds for such files, so try that. + // Though this will only help if the file is not a reparse point (symlink or not). + DWORD err = ::GetLastError(); + if (err == ERROR_ACCESS_DENIED) + { + DWORD attrs = ::GetFileAttributesW(p.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) + { + if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0u) + return fs::file_status((attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file, make_permissions(p, attrs)); + } + else + { + err = ::GetLastError(); + } + } + + return process_status_failure(err, p, ec); + } + + return detail::status_by_handle(h.handle, p, ec); +} + +//! status() implementation +fs::file_status status_impl(path const& p, error_code* ec) +{ + // We should first test if the file is a symlink or a reparse point. Resolving some reparse + // points by opening the file may fail, and status() should return file_status(reparse_file) in this case. + // Which is what symlink_status() returns. + fs::file_status st(detail::symlink_status_impl(p, ec)); + if (st.type() == symlink_file) + { + // Resolve the symlink + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, // see the comment in symlink_status_impl re. access mode + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttributes + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (h.handle == INVALID_HANDLE_VALUE) + return process_status_failure(p, ec); + + st = detail::status_by_handle(h.handle, p, ec); + } + + return st; +} + +//! remove() implementation for Windows XP and older +bool remove_nt5_impl(path const& p, DWORD attrs, error_code* ec) +{ + const bool is_directory = (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; + const bool is_read_only = (attrs & FILE_ATTRIBUTE_READONLY) != 0; + if (is_read_only) + { + // RemoveDirectoryW and DeleteFileW do not allow to remove a read-only file, so we have to drop the attribute + DWORD new_attrs = attrs & ~FILE_ATTRIBUTE_READONLY; + BOOL res = ::SetFileAttributesW(p.c_str(), new_attrs); + if (BOOST_UNLIKELY(!res)) + { + DWORD err = ::GetLastError(); + if (!not_found_error(err)) + emit_error(err, p, ec, "boost::filesystem::remove"); + + return false; + } + } + + BOOL res; + if (!is_directory) + { + // DeleteFileW works for file symlinks by removing the symlink, not the target. + res = ::DeleteFileW(p.c_str()); + } + else + { + // RemoveDirectoryW works for symlinks and junctions by removing the symlink, not the target, + // even if the target directory is not empty. + // Note that unlike opening the directory with FILE_FLAG_DELETE_ON_CLOSE flag, RemoveDirectoryW + // will fail if the directory is not empty. + res = ::RemoveDirectoryW(p.c_str()); + } + + if (BOOST_UNLIKELY(!res)) + { + DWORD err = ::GetLastError(); + if (!not_found_error(err)) + { + if (is_read_only) + { + // Try to restore the read-only attribute + ::SetFileAttributesW(p.c_str(), attrs); + } + + emit_error(err, p, ec, "boost::filesystem::remove"); + } + + return false; + } + + return true; +} + +//! remove() by handle implementation for Windows Vista and newer +DWORD remove_nt6_by_handle(HANDLE handle, remove_impl_type impl) +{ + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); + SetFileInformationByHandle_t* set_file_information_by_handle = filesystem::detail::atomic_load_relaxed(set_file_information_by_handle_api); + DWORD err = 0u; + switch (impl) + { + case remove_disp_ex_flag_ignore_readonly: + { + file_disposition_info_ex info; + info.Flags = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS | FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE; + BOOL res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); + if (BOOST_LIKELY(!!res)) + break; + + err = ::GetLastError(); + if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED || err == ERROR_CALL_NOT_IMPLEMENTED)) + { + // Downgrade to the older implementation + impl = remove_disp_ex_flag_posix_semantics; + filesystem::detail::atomic_store_relaxed(g_remove_impl_type, impl); + } + else + { + break; + } + } + BOOST_FALLTHROUGH; + + case remove_disp_ex_flag_posix_semantics: + { + file_disposition_info_ex info; + info.Flags = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS; + BOOL res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); + if (BOOST_LIKELY(!!res)) + { + err = 0u; + break; + } + + err = ::GetLastError(); + if (err == ERROR_ACCESS_DENIED) + { + // Check if the file is read-only and reset the attribute + file_basic_info basic_info; + res = get_file_information_by_handle_ex(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + if (BOOST_UNLIKELY(!res || (basic_info.FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)) + break; // return ERROR_ACCESS_DENIED + + basic_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + + res = set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + if (BOOST_UNLIKELY(!res)) + { + err = ::GetLastError(); + break; + } + + // Try to set the flag again + res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); + if (BOOST_LIKELY(!!res)) + { + err = 0u; + break; + } + + err = ::GetLastError(); + + // Try to restore the read-only flag + basic_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; + set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + + break; + } + else if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED || err == ERROR_CALL_NOT_IMPLEMENTED)) + { + // Downgrade to the older implementation + impl = remove_disp; + filesystem::detail::atomic_store_relaxed(g_remove_impl_type, impl); + } + else + { + break; + } + } + BOOST_FALLTHROUGH; + + default: + { + file_disposition_info info; + info.DeleteFile = true; + BOOL res = set_file_information_by_handle(handle, file_disposition_info_class, &info, sizeof(info)); + if (BOOST_LIKELY(!!res)) + { + err = 0u; + break; + } + + err = ::GetLastError(); + if (err == ERROR_ACCESS_DENIED) + { + // Check if the file is read-only and reset the attribute + file_basic_info basic_info; + res = get_file_information_by_handle_ex(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + if (BOOST_UNLIKELY(!res || (basic_info.FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)) + break; // return ERROR_ACCESS_DENIED + + basic_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + + res = set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + if (BOOST_UNLIKELY(!res)) + { + err = ::GetLastError(); + break; + } + + // Try to set the flag again + res = set_file_information_by_handle(handle, file_disposition_info_class, &info, sizeof(info)); + if (BOOST_LIKELY(!!res)) + { + err = 0u; + break; + } + + err = ::GetLastError(); + + // Try to restore the read-only flag + basic_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; + set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + } + + break; + } + } + + return err; +} + +//! remove() implementation for Windows Vista and newer +inline bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) +{ + handle_wrapper h(create_file_handle( + p, + DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + DWORD err = 0u; + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + err = ::GetLastError(); + + return_error: + if (!not_found_error(err)) + emit_error(err, p, ec, "boost::filesystem::remove"); + + return false; + } + + err = fs::detail::remove_nt6_by_handle(h.handle, impl); + if (BOOST_UNLIKELY(err != 0u)) + goto return_error; + + return true; +} + +//! remove() implementation +inline bool remove_impl(path const& p, error_code* ec) +{ + remove_impl_type impl = fs::detail::atomic_load_relaxed(g_remove_impl_type); + if (BOOST_LIKELY(impl != remove_nt5)) + { + return fs::detail::remove_nt6_impl(p, impl, ec); + } + else + { + const DWORD attrs = ::GetFileAttributesW(p.c_str()); + if (BOOST_UNLIKELY(attrs == INVALID_FILE_ATTRIBUTES)) + { + DWORD err = ::GetLastError(); + if (!not_found_error(err)) + emit_error(err, p, ec, "boost::filesystem::remove"); + + return false; + } + + return fs::detail::remove_nt5_impl(p, attrs, ec); + } +} + +#if !defined(UNDER_CE) + +//! remove_all() by handle implementation for Windows Vista and newer +uintmax_t remove_all_nt6_by_handle(HANDLE h, path const& p, error_code* ec) +{ + error_code local_ec; + fs::file_status st(fs::detail::status_by_handle(h, p, &local_ec)); + if (BOOST_UNLIKELY(st.type() == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, local_ec)); + + *ec = local_ec; + return static_cast< uintmax_t >(-1); + } + + uintmax_t count = 0u; + if (st.type() == fs::directory_file) + { + local_ec.clear(); + + fs::directory_iterator itr; + directory_iterator_params params; + params.use_handle = h; + params.close_handle = false; // the caller will close the handle + fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), ¶ms, &local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, local_ec)); + + *ec = local_ec; + return static_cast< uintmax_t >(-1); + } + + NtCreateFile_t* nt_create_file = filesystem::detail::atomic_load_relaxed(nt_create_file_api); + const fs::directory_iterator end_dit; + while (itr != end_dit) + { + fs::path nested_path(itr->path()); + handle_wrapper hh; + if (BOOST_LIKELY(nt_create_file != NULL)) + { + // Note: WinAPI methods like CreateFileW implicitly request SYNCHRONIZE access but NtCreateFile doesn't. + // Without SYNCHRONIZE access querying file attributes via GetFileInformationByHandleEx fails with ERROR_ACCESS_DENIED. + boost::winapi::NTSTATUS_ status = nt_create_file_handle_at + ( + hh.handle, + h, + path_algorithms::filename_v4(nested_path), + 0u, // FileAttributes + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT + ); + + if (!NT_SUCCESS(status)) + { + if (status == STATUS_NO_SUCH_FILE || + status == STATUS_OBJECT_NAME_NOT_FOUND || + status == STATUS_OBJECT_PATH_NOT_FOUND || + status == STATUS_BAD_NETWORK_PATH || + status == STATUS_BAD_NETWORK_NAME) + { + goto next_entry; + } + + DWORD err = translate_ntstatus(status); + emit_error(err, nested_path, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + } + else + { + hh.handle = create_file_handle( + nested_path, + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT); + + if (BOOST_UNLIKELY(hh.handle == INVALID_HANDLE_VALUE)) + { + DWORD err = ::GetLastError(); + if (not_found_error(err)) + goto next_entry; + + emit_error(err, nested_path, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + } + + count += fs::detail::remove_all_nt6_by_handle(hh.handle, nested_path, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + next_entry: + fs::detail::directory_iterator_increment(itr, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + } + } + + DWORD err = fs::detail::remove_nt6_by_handle(h, fs::detail::atomic_load_relaxed(g_remove_impl_type)); + if (BOOST_UNLIKELY(err != 0u)) + { + emit_error(err, p, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + + ++count; + return count; +} + +#endif // !defined(UNDER_CE) + +//! remove_all() implementation for Windows XP and older +uintmax_t remove_all_nt5_impl(path const& p, error_code* ec) +{ + error_code dit_create_ec; + for (unsigned int attempt = 0u; attempt < remove_all_directory_replaced_retry_count; ++attempt) + { + const DWORD attrs = ::GetFileAttributesW(p.c_str()); + if (BOOST_UNLIKELY(attrs == INVALID_FILE_ATTRIBUTES)) + { + DWORD err = ::GetLastError(); + if (not_found_error(err)) + return 0u; + + emit_error(err, p, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + + // Recurse into directories, but not into junctions or directory symlinks + const bool recurse = (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0 && (attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0; + uintmax_t count = 0u; + if (recurse) + { + fs::directory_iterator itr; + fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), NULL, &dit_create_ec); + if (BOOST_UNLIKELY(!!dit_create_ec)) + { + if (dit_create_ec == make_error_condition(system::errc::not_a_directory) || + dit_create_ec == make_error_condition(system::errc::too_many_symbolic_link_levels)) + { + continue; + } + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, dit_create_ec)); + + *ec = dit_create_ec; + return static_cast< uintmax_t >(-1); + } + + const fs::directory_iterator end_dit; + while (itr != end_dit) + { + count += fs::detail::remove_all_nt5_impl(itr->path(), ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + fs::detail::directory_iterator_increment(itr, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + } + } + + bool removed = fs::detail::remove_nt5_impl(p, attrs, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + count += removed; + return count; + } + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all: path cannot be opened as a directory", p, dit_create_ec)); + + *ec = dit_create_ec; + return static_cast< uintmax_t >(-1); +} + +//! remove_all() implementation +inline uintmax_t remove_all_impl(path const& p, error_code* ec) +{ +#if !defined(UNDER_CE) + remove_impl_type impl = fs::detail::atomic_load_relaxed(g_remove_impl_type); + if (BOOST_LIKELY(impl != remove_nt5)) + { + handle_wrapper h(create_file_handle( + p, + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + DWORD err = ::GetLastError(); + if (not_found_error(err)) + return 0u; + + emit_error(err, p, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + + return fs::detail::remove_all_nt6_by_handle(h.handle, p, ec); + } +#endif // !defined(UNDER_CE) + + return fs::detail::remove_all_nt5_impl(p, ec); +} + +inline BOOL resize_file_impl(const wchar_t* p, uintmax_t size) +{ + handle_wrapper h(CreateFileW(p, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); + LARGE_INTEGER sz; + sz.QuadPart = size; + return h.handle != INVALID_HANDLE_VALUE && ::SetFilePointerEx(h.handle, sz, 0, FILE_BEGIN) && ::SetEndOfFile(h.handle); +} + +//! Converts NT path to a Win32 path +inline path convert_nt_path_to_win32_path(const wchar_t* nt_path, std::size_t size) +{ + // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html + // https://stackoverflow.com/questions/23041983/path-prefixes-and + // + // NT paths can be used to identify practically any named objects, devices, files, local and remote shares, etc. + // The path starts with a leading backslash and consists of one or more path elements separated with backslashes. + // The set of characters allowed in NT path elements is significantly larger than that of Win32 paths - basically, + // any character except the backslash is allowed. Path elements are case-insensitive. + // + // NT paths that start with the "\??\" prefix are used to indicate the current user's session namespace. The prefix + // indicates to the NT object manager to lookup the object relative to "\Sessions\0\DosDevices\[Logon Authentication ID]". + // + // There is also a special "\Global??\" prefix that refers to the system logon. User's session directory shadows + // the system logon directory, so that when the referenced object is not found in the user's namespace, + // system logon is looked up instead. + // + // There is a symlink "Global" in the user's session namespace that refers to the global namespace, so "\??\Global" + // effectively resolves to "\Global??". This allows Win32 applications to directly refer to the system objects, + // even if shadowed by the current user's logon object. + // + // NT paths can be used to reference not only local filesystems, but also devices and remote shares identifiable via + // UNC paths. For this, there is a special "UNC" device (which is a symlink to "\Device\Mup") in the system logon + // namespace, so "\??\UNC\host\share" (or "\??\Global\UNC\host\share", or "\Global??\UNC\host\share") is equivalent + // to "\\host\share". + // + // NT paths are not universally accepted by Win32 applications and APIs. For example, Far supports paths starting + // with "\??\" and "\??\Global\" but not with "\Global??\". As of Win10 21H1, File Explorer, cmd.exe and PowerShell + // don't support any of these. Given this, and that NT paths have a different set of allowed characters from Win32 paths, + // we should normally avoid exposing NT paths to users that expect Win32 paths. + // + // In Boost.Filesystem we only deal with NT paths that come from reparse points, such as symlinks and mount points, + // including directory junctions. It was observed that reparse points created by junction.exe and mklink use the "\??\" + // prefix for directory junctions and absolute symlink and unqualified relative path for relative symlinks. + // Absolute paths are using drive letters for mounted drives (e.g. "\??\C:\directory"), although it is possible + // to create a junction to an directory using a different way of identifying the filesystem (e.g. + // "\??\Volume{00000000-0000-0000-0000-000000000000}\directory"). + // mklink does not support creating junctions pointing to a UNC path. junction.exe does create a junction that + // uses a seemingly invalid syntax like "\??\\\host\share", i.e. it basically does not expect an UNC path. It is not known + // if reparse points that refer to a UNC path are considered valid. + // There are reparse points created as mount points for local and remote filsystems (for example, a cloud storage mounted + // in the local filesystem). Such mount points have the form of "\??\Volume{00000000-0000-0000-0000-000000000000}\", + // "\??\Harddisk0Partition1\" or "\??\HarddiskVolume1\". + // Reparse points that refer directly to a global namespace (through "\??\Global\" or "\Global??\" prefixes) or + // devices (e.g. "\Device\HarddiskVolume1") have not been observed so far. + + path win32_path; + std::size_t pos = 0u; + bool global_namespace = false; + + // Check for the "\??\" prefix + if (size >= 4u && + nt_path[0] == path::preferred_separator && + nt_path[1] == questionmark && + nt_path[2] == questionmark && + nt_path[3] == path::preferred_separator) + { + pos = 4u; + + // Check "Global" + if ((size - pos) >= 6u && + (nt_path[pos] == L'G' || nt_path[pos] == L'g') && + (nt_path[pos + 1] == L'l' || nt_path[pos + 1] == L'L') && + (nt_path[pos + 2] == L'o' || nt_path[pos + 2] == L'O') && + (nt_path[pos + 3] == L'b' || nt_path[pos + 3] == L'B') && + (nt_path[pos + 4] == L'a' || nt_path[pos + 4] == L'A') && + (nt_path[pos + 5] == L'l' || nt_path[pos + 5] == L'L')) + { + if ((size - pos) == 6u) + { + pos += 6u; + global_namespace = true; + } + else if (detail::is_directory_separator(nt_path[pos + 6u])) + { + pos += 7u; + global_namespace = true; + } + } + } + // Check for the "\Global??\" prefix + else if (size >= 10u && + nt_path[0] == path::preferred_separator && + (nt_path[1] == L'G' || nt_path[1] == L'g') && + (nt_path[2] == L'l' || nt_path[2] == L'L') && + (nt_path[3] == L'o' || nt_path[3] == L'O') && + (nt_path[4] == L'b' || nt_path[4] == L'B') && + (nt_path[5] == L'a' || nt_path[5] == L'A') && + (nt_path[6] == L'l' || nt_path[6] == L'L') && + nt_path[7] == questionmark && + nt_path[8] == questionmark && + nt_path[9] == path::preferred_separator) + { + pos = 10u; + global_namespace = true; + } + + if (pos > 0u) + { + if ((size - pos) >= 2u && + ( + // Check if the following is a drive letter + ( + detail::is_letter(nt_path[pos]) && nt_path[pos + 1u] == colon && + ((size - pos) == 2u || detail::is_directory_separator(nt_path[pos + 2u])) + ) || + // Check for an "incorrect" syntax for UNC path junction points + ( + detail::is_directory_separator(nt_path[pos]) && detail::is_directory_separator(nt_path[pos + 1u]) && + ((size - pos) == 2u || !detail::is_directory_separator(nt_path[pos + 2u])) + ) + )) + { + // Strip the NT path prefix + goto done; + } + + static const wchar_t win32_path_prefix[4u] = { path::preferred_separator, path::preferred_separator, questionmark, path::preferred_separator }; + + // Check for a UNC path + if ((size - pos) >= 4u && + (nt_path[pos] == L'U' || nt_path[pos] == L'u') && + (nt_path[pos + 1] == L'N' || nt_path[pos + 1] == L'n') && + (nt_path[pos + 2] == L'C' || nt_path[pos + 2] == L'c') && + nt_path[pos + 3] == path::preferred_separator) + { + win32_path.assign(win32_path_prefix, win32_path_prefix + 2); + pos += 4u; + goto done; + } + + // This is some other NT path, possibly a volume mount point. Replace the NT prefix with a Win32 filesystem prefix "\\?\". + win32_path.assign(win32_path_prefix, win32_path_prefix + 4); + if (global_namespace) + { + static const wchar_t win32_path_global_prefix[7u] = { L'G', L'l', L'o', L'b', L'a', L'l', path::preferred_separator }; + win32_path.concat(win32_path_global_prefix, win32_path_global_prefix + 7); + } + } + +done: + win32_path.concat(nt_path + pos, nt_path + size); + return win32_path; +} + +#endif // defined(BOOST_POSIX_API) + +} // unnamed namespace +} // namespace detail + +//--------------------------------------------------------------------------------------// +// // +// operations functions declared in operations.hpp // +// // +//--------------------------------------------------------------------------------------// + +namespace detail { + +BOOST_FILESYSTEM_DECL bool possible_large_file_size_support() +{ +#ifdef BOOST_POSIX_API + typedef struct stat struct_stat; + return sizeof(struct_stat().st_size) > 4; +#else + return true; +#endif +} + +BOOST_FILESYSTEM_DECL +path absolute(path const& p, path const& base, system::error_code* ec) +{ + if (ec) + ec->clear(); + + if (p.is_absolute()) + return p; + + // recursively calling absolute is sub-optimal, but is sure and simple + path abs_base = base; + if (!base.is_absolute()) + { + if (ec) + { + abs_base = absolute(base, *ec); + if (*ec) + return path(); + } + else + { + abs_base = absolute(base); + } + } + + if (p.empty()) + return abs_base; + + path res; + if (p.has_root_name()) + res = p.root_name(); + else + res = abs_base.root_name(); + + if (p.has_root_directory()) + { + res.concat(p.root_directory()); + } + else + { + res.concat(abs_base.root_directory()); + path_algorithms::append_v4(res, abs_base.relative_path()); + } + + path p_relative_path(p.relative_path()); + if (!p_relative_path.empty()) + path_algorithms::append_v4(res, p_relative_path); + + return res; +} + +BOOST_FILESYSTEM_DECL +path canonical(path const& p, path const& base, system::error_code* ec) +{ + if (ec) + ec->clear(); + + path source(p); + if (!p.is_absolute()) + { + source = detail::absolute(p, base, ec); + if (ec && *ec) + { + return_empty_path: + return path(); + } + } + + system::error_code local_ec; + file_status st(detail::status_impl(source, &local_ec)); + + if (st.type() == fs::file_not_found) + { + local_ec = system::errc::make_error_code(system::errc::no_such_file_or_directory); + goto fail_local_ec; + } + else if (local_ec) + { + fail_local_ec: + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::canonical", source, local_ec)); + + *ec = local_ec; + goto return_empty_path; + } + + path root(source.root_path()); + path const& dot_p = dot_path(); + path const& dot_dot_p = dot_dot_path(); + unsigned int symlinks_allowed = symloop_max; + path result; + while (true) + { + for (path::iterator itr(source.begin()), end(source.end()); itr != end; path_algorithms::increment_v4(itr)) + { + if (path_algorithms::compare_v4(*itr, dot_p) == 0) + continue; + if (path_algorithms::compare_v4(*itr, dot_dot_p) == 0) + { + if (path_algorithms::compare_v4(result, root) != 0) + result.remove_filename_and_trailing_separators(); + continue; + } + + if (itr->size() == 1u && detail::is_directory_separator(itr->native()[0])) + { + // Convert generic separator returned by the iterator for the root directory to + // the preferred separator. This is important on Windows, as in some cases, + // like paths for network shares and cloud storage mount points GetFileAttributesW + // will return "file not found" if the path contains forward slashes. + result += path::preferred_separator; + // We don't need to check for a symlink after adding a separator. + continue; + } + + path_algorithms::append_v4(result, *itr); + + // If we don't have an absolute path yet then don't check symlink status. + // This avoids checking "C:" which is "the current directory on drive C" + // and hence not what we want to check/resolve here. + if (!result.is_absolute()) + continue; + + st = detail::symlink_status_impl(result, ec); + if (ec && *ec) + goto return_empty_path; + + if (is_symlink(st)) + { + if (symlinks_allowed == 0) + { + local_ec = system::errc::make_error_code(system::errc::too_many_symbolic_link_levels); + goto fail_local_ec; + } + + --symlinks_allowed; + + path link(detail::read_symlink(result, ec)); + if (ec && *ec) + goto return_empty_path; + result.remove_filename_and_trailing_separators(); + + if (link.is_absolute()) + { + for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr)) + { + if (path_algorithms::compare_v4(*itr, dot_p) != 0) + path_algorithms::append_v4(link, *itr); + } + source = link; + root = source.root_path(); + } + else // link is relative + { + link.remove_trailing_separator(); + if (path_algorithms::compare_v4(link, dot_p) == 0) + continue; + + path new_source(result); + path_algorithms::append_v4(new_source, link); + for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr)) + { + if (path_algorithms::compare_v4(*itr, dot_p) != 0) + path_algorithms::append_v4(new_source, *itr); + } + source = new_source; + } + + // symlink causes scan to be restarted + goto restart_scan; + } + } + + break; + + restart_scan: + result.clear(); + } + + BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report"); + return result; +} + +BOOST_FILESYSTEM_DECL +void copy(path const& from, path const& to, unsigned int options, system::error_code* ec) +{ + BOOST_ASSERT((((options & static_cast< unsigned int >(copy_options::overwrite_existing)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::update_existing)) != 0u)) <= 1); + + BOOST_ASSERT((((options & static_cast< unsigned int >(copy_options::copy_symlinks)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::skip_symlinks)) != 0u)) <= 1); + + BOOST_ASSERT((((options & static_cast< unsigned int >(copy_options::directories_only)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::create_symlinks)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::create_hard_links)) != 0u)) <= 1); + + if (ec) + ec->clear(); + + file_status from_stat; + if ((options & (static_cast< unsigned int >(copy_options::copy_symlinks) | + static_cast< unsigned int >(copy_options::skip_symlinks) | + static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) + { + from_stat = detail::symlink_status_impl(from, ec); + } + else + { + from_stat = detail::status_impl(from, ec); + } + + if (ec && *ec) + return; + + if (!exists(from_stat)) + { + emit_error(BOOST_ERROR_FILE_NOT_FOUND, from, to, ec, "boost::filesystem::copy"); + return; + } + + if (is_symlink(from_stat)) + { + if ((options & static_cast< unsigned int >(copy_options::skip_symlinks)) != 0u) + return; + + if ((options & static_cast< unsigned int >(copy_options::copy_symlinks)) == 0u) + goto fail; + + detail::copy_symlink(from, to, ec); + } + else if (is_regular_file(from_stat)) + { + if ((options & static_cast< unsigned int >(copy_options::directories_only)) != 0u) + return; + + if ((options & static_cast< unsigned int >(copy_options::create_symlinks)) != 0u) + { + const path* pfrom = &from; + path relative_from; + if (!from.is_absolute()) + { + // Try to generate a relative path from the target location to the original file + path cur_dir = detail::current_path(ec); + if (ec && *ec) + return; + path abs_from = detail::absolute(from.parent_path(), cur_dir, ec); + if (ec && *ec) + return; + path abs_to = to.parent_path(); + if (!abs_to.is_absolute()) + { + abs_to = detail::absolute(abs_to, cur_dir, ec); + if (ec && *ec) + return; + } + relative_from = detail::relative(abs_from, abs_to, ec); + if (ec && *ec) + return; + if (path_algorithms::compare_v4(relative_from, dot_path()) != 0) + path_algorithms::append_v4(relative_from, path_algorithms::filename_v4(from)); + else + relative_from = path_algorithms::filename_v4(from); + pfrom = &relative_from; + } + detail::create_symlink(*pfrom, to, ec); + return; + } + + if ((options & static_cast< unsigned int >(copy_options::create_hard_links)) != 0u) + { + detail::create_hard_link(from, to, ec); + return; + } + + error_code local_ec; + file_status to_stat; + if ((options & (static_cast< unsigned int >(copy_options::skip_symlinks) | + static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) + { + to_stat = detail::symlink_status_impl(to, &local_ec); + } + else + { + to_stat = detail::status_impl(to, &local_ec); + } + + // Note: local_ec may be set by (symlink_)status() even in some non-fatal situations, e.g. when the file does not exist. + // OTOH, when it returns status_error, then a real error have happened and it must have set local_ec. + if (to_stat.type() == fs::status_error) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy", from, to, local_ec)); + *ec = local_ec; + return; + } + + if (is_directory(to_stat)) + { + path target(to); + path_algorithms::append_v4(target, path_algorithms::filename_v4(from)); + detail::copy_file(from, target, options, ec); + } + else + detail::copy_file(from, to, options, ec); + } + else if (is_directory(from_stat)) + { + error_code local_ec; + if ((options & static_cast< unsigned int >(copy_options::create_symlinks)) != 0u) + { + local_ec = make_error_code(system::errc::is_a_directory); + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy", from, to, local_ec)); + *ec = local_ec; + return; + } + + file_status to_stat; + if ((options & (static_cast< unsigned int >(copy_options::skip_symlinks) | + static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) + { + to_stat = detail::symlink_status_impl(to, &local_ec); + } + else + { + to_stat = detail::status_impl(to, &local_ec); + } + + // Note: ec may be set by (symlink_)status() even in some non-fatal situations, e.g. when the file does not exist. + // OTOH, when it returns status_error, then a real error have happened and it must have set local_ec. + if (to_stat.type() == fs::status_error) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::copy", from, to, local_ec)); + *ec = local_ec; + return; + } + + if (!exists(to_stat)) + { + detail::create_directory(to, &from, ec); + if (ec && *ec) + return; + } + + if ((options & static_cast< unsigned int >(copy_options::recursive)) != 0u || options == 0u) + { + fs::directory_iterator itr; + detail::directory_iterator_construct(itr, from, static_cast< unsigned int >(directory_options::none), NULL, ec); + if (ec && *ec) + return; + + const fs::directory_iterator end_dit; + while (itr != end_dit) + { + path const& p = itr->path(); + { + path target(to); + path_algorithms::append_v4(target, path_algorithms::filename_v4(p)); + // Set _detail_recursing flag so that we don't recurse more than for one level deeper into the directory if options are copy_options::none + detail::copy(p, target, options | static_cast< unsigned int >(copy_options::_detail_recursing), ec); + } + if (ec && *ec) + return; + + detail::directory_iterator_increment(itr, ec); + if (ec && *ec) + return; + } + } + } + else + { + fail: + emit_error(BOOST_ERROR_NOT_SUPPORTED, from, to, ec, "boost::filesystem::copy"); + } +} + +BOOST_FILESYSTEM_DECL +bool copy_file(path const& from, path const& to, unsigned int options, error_code* ec) +{ + BOOST_ASSERT((((options & static_cast< unsigned int >(copy_options::overwrite_existing)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) + + ((options & static_cast< unsigned int >(copy_options::update_existing)) != 0u)) <= 1); + + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + + int err = 0; + + // Note: Declare fd_wrappers here so that errno is not clobbered by close() that may be called in fd_wrapper destructors + fd_wrapper infile, outfile; + + while (true) + { + infile.fd = ::open(from.c_str(), O_RDONLY | O_CLOEXEC); + if (BOOST_UNLIKELY(infile.fd < 0)) + { + err = errno; + if (err == EINTR) + continue; + + fail: + emit_error(err, from, to, ec, "boost::filesystem::copy_file"); + return false; + } + + break; + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + unsigned int statx_data_mask = STATX_TYPE | STATX_MODE | STATX_INO | STATX_SIZE; + if ((options & static_cast< unsigned int >(copy_options::update_existing)) != 0u) + statx_data_mask |= STATX_MTIME; + + struct ::statx from_stat; + if (BOOST_UNLIKELY(invoke_statx(infile.fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT, statx_data_mask, &from_stat) < 0)) + { + fail_errno: + err = errno; + goto fail; + } + + if (BOOST_UNLIKELY((from_stat.stx_mask & statx_data_mask) != statx_data_mask)) + { + err = ENOSYS; + goto fail; + } +#else + struct ::stat from_stat; + if (BOOST_UNLIKELY(::fstat(infile.fd, &from_stat) != 0)) + { + fail_errno: + err = errno; + goto fail; + } +#endif + + const mode_t from_mode = get_mode(from_stat); + if (BOOST_UNLIKELY(!S_ISREG(from_mode))) + { + err = ENOSYS; + goto fail; + } + + mode_t to_mode = from_mode; +#if !defined(BOOST_FILESYSTEM_USE_WASI) + // Enable writing for the newly created files. Having write permission set is important e.g. for NFS, + // which checks the file permission on the server, even if the client's file descriptor supports writing. + to_mode |= S_IWUSR; +#endif + int oflag = O_WRONLY | O_CLOEXEC; + + if ((options & static_cast< unsigned int >(copy_options::update_existing)) != 0u) + { + // Try opening the existing file without truncation to test the modification time later + while (true) + { + outfile.fd = ::open(to.c_str(), oflag, to_mode); + if (outfile.fd < 0) + { + err = errno; + if (err == EINTR) + continue; + + if (err == ENOENT) + goto create_outfile; + + goto fail; + } + + break; + } + } + else + { + create_outfile: + oflag |= O_CREAT | O_TRUNC; + if (((options & static_cast< unsigned int >(copy_options::overwrite_existing)) == 0u || + (options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) && + (options & static_cast< unsigned int >(copy_options::update_existing)) == 0u) + { + oflag |= O_EXCL; + } + + while (true) + { + outfile.fd = ::open(to.c_str(), oflag, to_mode); + if (outfile.fd < 0) + { + err = errno; + if (err == EINTR) + continue; + + if (err == EEXIST && (options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) + return false; + + goto fail; + } + + break; + } + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + statx_data_mask = STATX_TYPE | STATX_MODE | STATX_INO; + if ((oflag & O_TRUNC) == 0) + { + // O_TRUNC is not set if copy_options::update_existing is set and an existing file was opened. + statx_data_mask |= STATX_MTIME; + } + + struct ::statx to_stat; + if (BOOST_UNLIKELY(invoke_statx(outfile.fd, "", AT_EMPTY_PATH | AT_NO_AUTOMOUNT, statx_data_mask, &to_stat) < 0)) + goto fail_errno; + + if (BOOST_UNLIKELY((to_stat.stx_mask & statx_data_mask) != statx_data_mask)) + { + err = ENOSYS; + goto fail; + } +#else + struct ::stat to_stat; + if (BOOST_UNLIKELY(::fstat(outfile.fd, &to_stat) != 0)) + goto fail_errno; +#endif + + to_mode = get_mode(to_stat); + if (BOOST_UNLIKELY(!S_ISREG(to_mode))) + { + err = ENOSYS; + goto fail; + } + + if (BOOST_UNLIKELY(detail::equivalent_stat(from_stat, to_stat))) + { + err = EEXIST; + goto fail; + } + + if ((oflag & O_TRUNC) == 0) + { + // O_TRUNC is not set if copy_options::update_existing is set and an existing file was opened. + // We need to check the last write times. +#if defined(BOOST_FILESYSTEM_USE_STATX) + if (from_stat.stx_mtime.tv_sec < to_stat.stx_mtime.tv_sec || (from_stat.stx_mtime.tv_sec == to_stat.stx_mtime.tv_sec && from_stat.stx_mtime.tv_nsec <= to_stat.stx_mtime.tv_nsec)) + return false; +#elif defined(BOOST_FILESYSTEM_STAT_ST_MTIMENSEC) + // Modify time is available with nanosecond precision. + if (from_stat.st_mtime < to_stat.st_mtime || (from_stat.st_mtime == to_stat.st_mtime && from_stat.BOOST_FILESYSTEM_STAT_ST_MTIMENSEC <= to_stat.BOOST_FILESYSTEM_STAT_ST_MTIMENSEC)) + return false; +#else + if (from_stat.st_mtime <= to_stat.st_mtime) + return false; +#endif + + if (BOOST_UNLIKELY(::ftruncate(outfile.fd, 0) != 0)) + goto fail_errno; + } + + // Note: Use block size of the target file since it is most important for writing performance. + err = filesystem::detail::atomic_load_relaxed(filesystem::detail::copy_file_data)(infile.fd, outfile.fd, get_size(from_stat), get_blksize(to_stat)); + if (BOOST_UNLIKELY(err != 0)) + goto fail; // err already contains the error code + +#if !defined(BOOST_FILESYSTEM_USE_WASI) + // If we created a new file with an explicitly added S_IWUSR permission, + // we may need to update its mode bits to match the source file. + if (to_mode != from_mode) + { + if (BOOST_UNLIKELY(::fchmod(outfile.fd, from_mode) != 0)) + goto fail_errno; + } +#endif + + if ((options & (static_cast< unsigned int >(copy_options::synchronize_data) | static_cast< unsigned int >(copy_options::synchronize))) != 0u) + { + if ((options & static_cast< unsigned int >(copy_options::synchronize)) != 0u) + err = full_sync(outfile.fd); + else + err = data_sync(outfile.fd); + + if (BOOST_UNLIKELY(err != 0)) + goto fail; + } + + // We have to explicitly close the output file descriptor in order to handle a possible error returned from it. The error may indicate + // a failure of a prior write operation. + err = close_fd(outfile.fd); + outfile.fd = -1; + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + // EINPROGRESS is an allowed error code in future POSIX revisions, according to https://www.austingroupbugs.net/view.php?id=529#c1200. + if (err != EINTR && err != EINPROGRESS) + goto fail; + } + + return true; + +#else // defined(BOOST_POSIX_API) + + DWORD copy_flags = 0u; + if ((options & static_cast< unsigned int >(copy_options::overwrite_existing)) == 0u || + (options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) + { + copy_flags |= COPY_FILE_FAIL_IF_EXISTS; + } + + if ((options & static_cast< unsigned int >(copy_options::update_existing)) != 0u) + { + // Create handle_wrappers here so that CloseHandle calls don't clobber error code returned by GetLastError + handle_wrapper hw_from, hw_to; + + // See the comment in last_write_time regarding access rights used here for GetFileTime. + hw_from.handle = create_file_handle( + from.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS); + + FILETIME lwt_from; + if (hw_from.handle == INVALID_HANDLE_VALUE) + { + fail_last_error: + DWORD err = ::GetLastError(); + emit_error(err, from, to, ec, "boost::filesystem::copy_file"); + return false; + } + + if (!::GetFileTime(hw_from.handle, NULL, NULL, &lwt_from)) + goto fail_last_error; + + hw_to.handle = create_file_handle( + to.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS); + + if (hw_to.handle != INVALID_HANDLE_VALUE) + { + FILETIME lwt_to; + if (!::GetFileTime(hw_to.handle, NULL, NULL, &lwt_to)) + goto fail_last_error; + + ULONGLONG tfrom = (static_cast< ULONGLONG >(lwt_from.dwHighDateTime) << 32) | static_cast< ULONGLONG >(lwt_from.dwLowDateTime); + ULONGLONG tto = (static_cast< ULONGLONG >(lwt_to.dwHighDateTime) << 32) | static_cast< ULONGLONG >(lwt_to.dwLowDateTime); + if (tfrom <= tto) + return false; + } + + copy_flags &= ~static_cast< DWORD >(COPY_FILE_FAIL_IF_EXISTS); + } + + struct callback_context + { + DWORD flush_error; + }; + + struct local + { + //! Callback that is called to report progress of \c CopyFileExW + static DWORD WINAPI on_copy_file_progress( + LARGE_INTEGER total_file_size, + LARGE_INTEGER total_bytes_transferred, + LARGE_INTEGER stream_size, + LARGE_INTEGER stream_bytes_transferred, + DWORD stream_number, + DWORD callback_reason, + HANDLE from_handle, + HANDLE to_handle, + LPVOID ctx) + { + // For each stream, CopyFileExW will open a separate pair of file handles, so we need to flush each stream separately. + if (stream_bytes_transferred.QuadPart == stream_size.QuadPart) + { + BOOL res = ::FlushFileBuffers(to_handle); + if (BOOST_UNLIKELY(!res)) + { + callback_context* context = static_cast< callback_context* >(ctx); + if (BOOST_LIKELY(context->flush_error == 0u)) + context->flush_error = ::GetLastError(); + } + } + + return PROGRESS_CONTINUE; + } + }; + + callback_context cb_context = {}; + LPPROGRESS_ROUTINE cb = NULL; + LPVOID cb_ctx = NULL; + + if ((options & (static_cast< unsigned int >(copy_options::synchronize_data) | static_cast< unsigned int >(copy_options::synchronize))) != 0u) + { + cb = &local::on_copy_file_progress; + cb_ctx = &cb_context; + } + + BOOL cancelled = FALSE; + BOOL res = ::CopyFileExW(from.c_str(), to.c_str(), cb, cb_ctx, &cancelled, copy_flags); + DWORD err; + if (BOOST_UNLIKELY(!res)) + { + err = ::GetLastError(); + if ((err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS) && (options & static_cast< unsigned int >(copy_options::skip_existing)) != 0u) + return false; + + copy_failed: + emit_error(err, from, to, ec, "boost::filesystem::copy_file"); + return false; + } + + if (BOOST_UNLIKELY(cb_context.flush_error != 0u)) + { + err = cb_context.flush_error; + goto copy_failed; + } + + return true; + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +void copy_symlink(path const& existing_symlink, path const& new_symlink, system::error_code* ec) +{ + path p(read_symlink(existing_symlink, ec)); + if (ec && *ec) + return; + create_symlink(p, new_symlink, ec); +} + +BOOST_FILESYSTEM_DECL +bool create_directories(path const& p, system::error_code* ec) +{ + if (p.empty()) + { + if (!ec) + { + BOOST_FILESYSTEM_THROW(filesystem_error( + "boost::filesystem::create_directories", p, + system::errc::make_error_code(system::errc::invalid_argument))); + } + ec->assign(system::errc::invalid_argument, system::generic_category()); + return false; + } + + if (ec) + ec->clear(); + + path::const_iterator e(p.end()), it(e); + path parent(p); + path const& dot_p = dot_path(); + path const& dot_dot_p = dot_dot_path(); + error_code local_ec; + + // Find the initial part of the path that exists + for (path fname = path_algorithms::filename_v4(parent); parent.has_relative_path(); fname = path_algorithms::filename_v4(parent)) + { + if (!fname.empty() && path_algorithms::compare_v4(fname, dot_p) != 0 && path_algorithms::compare_v4(fname, dot_dot_p) != 0) + { + file_status existing_status = detail::status_impl(parent, &local_ec); + + if (existing_status.type() == directory_file) + { + break; + } + else if (BOOST_UNLIKELY(existing_status.type() == status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", p, parent, local_ec)); + *ec = local_ec; + return false; + } + } + + path_algorithms::decrement_v4(it); + parent.remove_filename_and_trailing_separators(); + } + + // Create missing directories + bool created = false; + for (; it != e; path_algorithms::increment_v4(it)) + { + path const& fname = *it; + path_algorithms::append_v4(parent, fname); + if (!fname.empty() && path_algorithms::compare_v4(fname, dot_p) != 0 && path_algorithms::compare_v4(fname, dot_dot_p) != 0) + { + created = detail::create_directory(parent, NULL, &local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::create_directories", p, parent, local_ec)); + *ec = local_ec; + return false; + } + } + } + + return created; +} + +BOOST_FILESYSTEM_DECL +bool create_directory(path const& p, const path* existing, error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + + mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO; + if (existing) + { +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx existing_stat; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, existing->c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &existing_stat) < 0)) + { + emit_error(errno, p, *existing, ec, "boost::filesystem::create_directory"); + return false; + } + + if (BOOST_UNLIKELY((existing_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, *existing, ec, "boost::filesystem::create_directory"); + return false; + } +#else + struct ::stat existing_stat; + if (::stat(existing->c_str(), &existing_stat) < 0) + { + emit_error(errno, p, *existing, ec, "boost::filesystem::create_directory"); + return false; + } +#endif + + const mode_t existing_mode = get_mode(existing_stat); + if (!S_ISDIR(existing_mode)) + { + emit_error(ENOTDIR, p, *existing, ec, "boost::filesystem::create_directory"); + return false; + } + + mode = existing_mode; + } + + if (::mkdir(p.c_str(), mode) == 0) + return true; + +#else // defined(BOOST_POSIX_API) + + BOOL res; + if (existing) + res = ::CreateDirectoryExW(existing->c_str(), p.c_str(), NULL); + else + res = ::CreateDirectoryW(p.c_str(), NULL); + + if (res) + return true; + +#endif // defined(BOOST_POSIX_API) + + // attempt to create directory failed + err_t errval = BOOST_ERRNO; // save reason for failure + error_code dummy; + + if (is_directory(p, dummy)) + return false; + + // attempt to create directory failed && it doesn't already exist + emit_error(errval, p, ec, "boost::filesystem::create_directory"); + return false; +} + +// Deprecated, to be removed in a future release +BOOST_FILESYSTEM_DECL +void copy_directory(path const& from, path const& to, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + int err; + struct ::statx from_stat; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, from.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &from_stat) < 0)) + { + fail_errno: + err = errno; + fail: + emit_error(err, from, to, ec, "boost::filesystem::copy_directory"); + return; + } + + if (BOOST_UNLIKELY((from_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + err = BOOST_ERROR_NOT_SUPPORTED; + goto fail; + } +#else + struct ::stat from_stat; + if (BOOST_UNLIKELY(::stat(from.c_str(), &from_stat) < 0)) + { + fail_errno: + emit_error(errno, from, to, ec, "boost::filesystem::copy_directory"); + return; + } +#endif + + if (BOOST_UNLIKELY(::mkdir(to.c_str(), get_mode(from_stat)) < 0)) + goto fail_errno; + +#else // defined(BOOST_POSIX_API) + + if (BOOST_UNLIKELY(!::CreateDirectoryExW(from.c_str(), to.c_str(), 0))) + emit_error(BOOST_ERRNO, from, to, ec, "boost::filesystem::copy_directory"); + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +void create_directory_symlink(path const& to, path const& from, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + int err = ::symlink(to.c_str(), from.c_str()); + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + emit_error(err, to, from, ec, "boost::filesystem::create_directory_symlink"); + } +#else + // see if actually supported by Windows runtime dll + if (!create_symbolic_link_api) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec, "boost::filesystem::create_directory_symlink"); + return; + } + + if (!create_symbolic_link_api(from.c_str(), to.c_str(), SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) + { + emit_error(BOOST_ERRNO, to, from, ec, "boost::filesystem::create_directory_symlink"); + } +#endif +} + +BOOST_FILESYSTEM_DECL +void create_hard_link(path const& to, path const& from, error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + int err = ::link(to.c_str(), from.c_str()); + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + emit_error(err, to, from, ec, "boost::filesystem::create_hard_link"); + } +#else + // see if actually supported by Windows runtime dll + CreateHardLinkW_t* chl_api = filesystem::detail::atomic_load_relaxed(create_hard_link_api); + if (BOOST_UNLIKELY(!chl_api)) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec, "boost::filesystem::create_hard_link"); + return; + } + + if (BOOST_UNLIKELY(!chl_api(from.c_str(), to.c_str(), NULL))) + { + emit_error(BOOST_ERRNO, to, from, ec, "boost::filesystem::create_hard_link"); + } +#endif +} + +BOOST_FILESYSTEM_DECL +void create_symlink(path const& to, path const& from, error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + int err = ::symlink(to.c_str(), from.c_str()); + if (BOOST_UNLIKELY(err < 0)) + { + err = errno; + emit_error(err, to, from, ec, "boost::filesystem::create_symlink"); + } +#else + // see if actually supported by Windows runtime dll + CreateSymbolicLinkW_t* csl_api = filesystem::detail::atomic_load_relaxed(create_symbolic_link_api); + if (BOOST_UNLIKELY(!csl_api)) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, to, from, ec, "boost::filesystem::create_symlink"); + return; + } + + if (BOOST_UNLIKELY(!csl_api(from.c_str(), to.c_str(), SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))) + { + emit_error(BOOST_ERRNO, to, from, ec, "boost::filesystem::create_symlink"); + } +#endif +} + +BOOST_FILESYSTEM_DECL +path current_path(error_code* ec) +{ +#if defined(UNDER_CE) || defined(BOOST_FILESYSTEM_USE_WASI) + // Windows CE has no current directory, so everything's relative to the root of the directory tree. + // WASI also does not support current path. + emit_error(BOOST_ERROR_NOT_SUPPORTED, ec, "boost::filesystem::current_path"); + return path(); +#elif defined(BOOST_POSIX_API) + struct local + { + static bool getcwd_error(error_code* ec) + { + const int err = errno; + return error((err != ERANGE +#if defined(__MSL__) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) + // bug in some versions of the Metrowerks C lib on the Mac: wrong errno set + && err != 0 +#endif + ) ? err : 0, + ec, "boost::filesystem::current_path"); + } + }; + + path cur; + char small_buf[small_path_size]; + const char* p = ::getcwd(small_buf, sizeof(small_buf)); + if (BOOST_LIKELY(!!p)) + { + cur = p; + if (ec) + ec->clear(); + } + else if (BOOST_LIKELY(!local::getcwd_error(ec))) + { + for (std::size_t path_max = sizeof(small_buf) * 2u;; path_max *= 2u) // loop 'til buffer large enough + { + if (BOOST_UNLIKELY(path_max > absolute_path_max)) + { + emit_error(ENAMETOOLONG, ec, "boost::filesystem::current_path"); + break; + } + + boost::scoped_array< char > buf(new char[path_max]); + p = ::getcwd(buf.get(), path_max); + if (BOOST_LIKELY(!!p)) + { + cur = buf.get(); + if (ec) + ec->clear(); + break; + } + else if (BOOST_UNLIKELY(local::getcwd_error(ec))) + { + break; + } + } + } + + return cur; +#else + DWORD sz; + if ((sz = ::GetCurrentDirectoryW(0, NULL)) == 0) + sz = 1; + boost::scoped_array< path::value_type > buf(new path::value_type[sz]); + error(::GetCurrentDirectoryW(sz, buf.get()) == 0 ? BOOST_ERRNO : 0, ec, "boost::filesystem::current_path"); + return path(buf.get()); +#endif +} + +BOOST_FILESYSTEM_DECL +void current_path(path const& p, system::error_code* ec) +{ +#if defined(UNDER_CE) || defined(BOOST_FILESYSTEM_USE_WASI) + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::current_path"); +#else + error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::current_path"); +#endif +} + +BOOST_FILESYSTEM_DECL +bool equivalent(path const& p1, path const& p2, system::error_code* ec) +{ +#if defined(BOOST_POSIX_API) + + // p2 is done first, so any error reported is for p1 +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx s2; + int e2 = invoke_statx(AT_FDCWD, p2.c_str(), AT_NO_AUTOMOUNT, STATX_INO, &s2); + if (BOOST_LIKELY(e2 == 0)) + { + if (BOOST_UNLIKELY((s2.stx_mask & STATX_INO) != STATX_INO)) + { + fail_unsupported: + emit_error(BOOST_ERROR_NOT_SUPPORTED, p1, p2, ec, "boost::filesystem::equivalent"); + return false; + } + } + + struct ::statx s1; + int e1 = invoke_statx(AT_FDCWD, p1.c_str(), AT_NO_AUTOMOUNT, STATX_INO, &s1); + if (BOOST_LIKELY(e1 == 0)) + { + if (BOOST_UNLIKELY((s1.stx_mask & STATX_INO) != STATX_INO)) + goto fail_unsupported; + } +#else + struct ::stat s2; + int e2 = ::stat(p2.c_str(), &s2); + struct ::stat s1; + int e1 = ::stat(p1.c_str(), &s1); +#endif + + if (BOOST_UNLIKELY(e1 != 0 || e2 != 0)) + { + // if one is invalid and the other isn't then they aren't equivalent, + // but if both are invalid then it is an error + if (e1 != 0 && e2 != 0) + emit_error(errno, p1, p2, ec, "boost::filesystem::equivalent"); + return false; + } + + return equivalent_stat(s1, s2); + +#else // Windows + + // Thanks to Jeremy Maitin-Shepard for much help and for permission to + // base the equivalent() implementation on portions of his + // file-equivalence-win32.cpp experimental code. + + // Note well: Physical location on external media is part of the + // equivalence criteria. If there are no open handles, physical location + // can change due to defragmentation or other relocations. Thus handles + // must be held open until location information for both paths has + // been retrieved. + + // p2 is done first, so any error reported is for p1 + handle_wrapper h2(create_file_handle( + p2.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + handle_wrapper h1(create_file_handle( + p1.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (BOOST_UNLIKELY(h1.handle == INVALID_HANDLE_VALUE || h2.handle == INVALID_HANDLE_VALUE)) + { + // if one is invalid and the other isn't, then they aren't equivalent, + // but if both are invalid then it is an error + if (h1.handle == INVALID_HANDLE_VALUE && h2.handle == INVALID_HANDLE_VALUE) + error(BOOST_ERRNO, p1, p2, ec, "boost::filesystem::equivalent"); + return false; + } + + // at this point, both handles are known to be valid + + BY_HANDLE_FILE_INFORMATION info1, info2; + + if (error(!::GetFileInformationByHandle(h1.handle, &info1) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + + if (error(!::GetFileInformationByHandle(h2.handle, &info2) ? BOOST_ERRNO : 0, p1, p2, ec, "boost::filesystem::equivalent")) + return false; + + // In theory, volume serial numbers are sufficient to distinguish between + // devices, but in practice VSN's are sometimes duplicated, so last write + // time and file size are also checked. + return info1.dwVolumeSerialNumber == info2.dwVolumeSerialNumber && + info1.nFileIndexHigh == info2.nFileIndexHigh && + info1.nFileIndexLow == info2.nFileIndexLow && + info1.nFileSizeHigh == info2.nFileSizeHigh && + info1.nFileSizeLow == info2.nFileSizeLow && + info1.ftLastWriteTime.dwLowDateTime == info2.ftLastWriteTime.dwLowDateTime && + info1.ftLastWriteTime.dwHighDateTime == info2.ftLastWriteTime.dwHighDateTime; + +#endif +} + +BOOST_FILESYSTEM_DECL +uintmax_t file_size(path const& p, error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_SIZE, &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } + + if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_SIZE)) != (STATX_TYPE | STATX_SIZE) || !S_ISREG(path_stat.stx_mode))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } +#else + struct ::stat path_stat; + if (BOOST_UNLIKELY(::stat(p.c_str(), &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } + + if (BOOST_UNLIKELY(!S_ISREG(path_stat.st_mode))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } +#endif + + return get_size(path_stat); + +#else // defined(BOOST_POSIX_API) + + // assume uintmax_t is 64-bits on all Windows compilers + + WIN32_FILE_ATTRIBUTE_DATA fad; + + if (BOOST_UNLIKELY(!::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad))) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } + + if (BOOST_UNLIKELY((fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) + { + emit_error(ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::file_size"); + return static_cast< uintmax_t >(-1); + } + + return (static_cast< uintmax_t >(fad.nFileSizeHigh) + << (sizeof(fad.nFileSizeLow) * 8u)) | + fad.nFileSizeLow; + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +uintmax_t hard_link_count(path const& p, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_NLINK, &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::hard_link_count"); + return static_cast< uintmax_t >(-1); + } + + if (BOOST_UNLIKELY((path_stat.stx_mask & STATX_NLINK) != STATX_NLINK)) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::hard_link_count"); + return static_cast< uintmax_t >(-1); + } + + return static_cast< uintmax_t >(path_stat.stx_nlink); +#else + struct ::stat path_stat; + if (BOOST_UNLIKELY(::stat(p.c_str(), &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::hard_link_count"); + return static_cast< uintmax_t >(-1); + } + + return static_cast< uintmax_t >(path_stat.st_nlink); +#endif + +#else // defined(BOOST_POSIX_API) + + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + fail_errno: + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::hard_link_count"); + return static_cast< uintmax_t >(-1); + } + + // Link count info is only available through GetFileInformationByHandle + BY_HANDLE_FILE_INFORMATION info; + if (BOOST_UNLIKELY(!::GetFileInformationByHandle(h.handle, &info))) + goto fail_errno; + + return static_cast< uintmax_t >(info.nNumberOfLinks); + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +path initial_path(error_code* ec) +{ + static path init_path; + if (init_path.empty()) + init_path = current_path(ec); + else if (ec) + ec->clear(); + return init_path; +} + +BOOST_FILESYSTEM_DECL +bool is_empty(path const& p, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_SIZE, &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::is_empty"); + return false; + } + + if (BOOST_UNLIKELY((path_stat.stx_mask & STATX_TYPE) != STATX_TYPE)) + { + fail_unsupported: + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::is_empty"); + return false; + } + + if (S_ISDIR(get_mode(path_stat))) + return is_empty_directory(p, ec); + + if (BOOST_UNLIKELY((path_stat.stx_mask & STATX_SIZE) != STATX_SIZE)) + goto fail_unsupported; + + return get_size(path_stat) == 0u; +#else + struct ::stat path_stat; + if (BOOST_UNLIKELY(::stat(p.c_str(), &path_stat) < 0)) + { + emit_error(errno, p, ec, "boost::filesystem::is_empty"); + return false; + } + + return S_ISDIR(get_mode(path_stat)) ? is_empty_directory(p, ec) : get_size(path_stat) == 0u; +#endif + +#else // defined(BOOST_POSIX_API) + + WIN32_FILE_ATTRIBUTE_DATA fad; + if (BOOST_UNLIKELY(!::GetFileAttributesExW(p.c_str(), ::GetFileExInfoStandard, &fad))) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::is_empty"); + return false; + } + + return (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? is_empty_directory(p, ec) : (!fad.nFileSizeHigh && !fad.nFileSizeLow); + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +std::time_t creation_time(path const& p, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx stx; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_BTIME, &stx) < 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::creation_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + if (BOOST_UNLIKELY((stx.stx_mask & STATX_BTIME) != STATX_BTIME)) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::creation_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + return stx.stx_btime.tv_sec; +#elif defined(BOOST_FILESYSTEM_STAT_ST_BIRTHTIME) && defined(BOOST_FILESYSTEM_STAT_ST_BIRTHTIMENSEC) + struct ::stat st; + if (BOOST_UNLIKELY(::stat(p.c_str(), &st) < 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::creation_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + return st.BOOST_FILESYSTEM_STAT_ST_BIRTHTIME; +#else + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::creation_time"); + return (std::numeric_limits< std::time_t >::min)(); +#endif + +#else // defined(BOOST_POSIX_API) + + // See the comment in last_write_time regarding access rights used here for GetFileTime. + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) + { + fail: + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::creation_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + + FILETIME ct; + if (BOOST_UNLIKELY(!::GetFileTime(hw.handle, &ct, NULL, NULL))) + goto fail; + + return to_time_t(ct); + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +std::time_t last_write_time(path const& p, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx stx; + if (BOOST_UNLIKELY(invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_MTIME, &stx) < 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + if (BOOST_UNLIKELY((stx.stx_mask & STATX_MTIME) != STATX_MTIME)) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::last_write_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + return stx.stx_mtime.tv_sec; +#else + struct ::stat st; + if (BOOST_UNLIKELY(::stat(p.c_str(), &st) < 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + return st.st_mtime; +#endif + +#else // defined(BOOST_POSIX_API) + + // GetFileTime is documented to require GENERIC_READ access right, but this causes problems if the file + // is opened by another process without FILE_SHARE_READ. In practice, FILE_READ_ATTRIBUTES works, and + // FILE_READ_EA is also added for good measure, in case if it matters for SMBv1. + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) + { + fail: + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return (std::numeric_limits< std::time_t >::min)(); + } + + FILETIME lwt; + if (BOOST_UNLIKELY(!::GetFileTime(hw.handle, NULL, NULL, &lwt))) + goto fail; + + return to_time_t(lwt); + +#endif // defined(BOOST_POSIX_API) +} + +BOOST_FILESYSTEM_DECL +void last_write_time(path const& p, const std::time_t new_time, system::error_code* ec) +{ + if (ec) + ec->clear(); + +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + + struct timespec times[2] = {}; + + // Keep the last access time unchanged + times[0].tv_nsec = UTIME_OMIT; + + times[1].tv_sec = new_time; + + if (BOOST_UNLIKELY(::utimensat(AT_FDCWD, p.c_str(), times, 0) != 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return; + } + +#else // defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + + struct ::stat st; + if (BOOST_UNLIKELY(::stat(p.c_str(), &st) < 0)) + { + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return; + } + + ::utimbuf buf; + buf.actime = st.st_atime; // utime() updates access time too :-( + buf.modtime = new_time; + if (BOOST_UNLIKELY(::utime(p.c_str(), &buf) < 0)) + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + +#endif // defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + +#else // defined(BOOST_POSIX_API) + + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) + { + fail: + emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); + return; + } + + FILETIME lwt; + to_FILETIME(new_time, lwt); + + if (BOOST_UNLIKELY(!::SetFileTime(hw.handle, NULL, NULL, &lwt))) + goto fail; + +#endif // defined(BOOST_POSIX_API) +} + +#ifdef BOOST_POSIX_API +const perms active_bits(all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit); +inline mode_t mode_cast(perms prms) +{ + return prms & active_bits; +} +#endif + +BOOST_FILESYSTEM_DECL +void permissions(path const& p, perms prms, system::error_code* ec) +{ + BOOST_ASSERT_MSG(!((prms & add_perms) && (prms & remove_perms)), "add_perms and remove_perms are mutually exclusive"); + + if ((prms & add_perms) && (prms & remove_perms)) // precondition failed + return; + +#if defined(BOOST_FILESYSTEM_USE_WASI) + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::permissions"); +#elif defined(BOOST_POSIX_API) + error_code local_ec; + file_status current_status((prms & symlink_perms) ? detail::symlink_status_impl(p, &local_ec) : detail::status_impl(p, &local_ec)); + if (local_ec) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::permissions", p, local_ec)); + + *ec = local_ec; + return; + } + + if (prms & add_perms) + prms |= current_status.permissions(); + else if (prms & remove_perms) + prms = current_status.permissions() & ~prms; + + // OS X <10.10, iOS <8.0 and some other platforms don't support fchmodat(). + // Solaris (SunPro and gcc) only support fchmodat() on Solaris 11 and higher, + // and a runtime check is too much trouble. + // Linux does not support permissions on symbolic links and has no plans to + // support them in the future. The chmod() code is thus more practical, + // rather than always hitting ENOTSUP when sending in AT_SYMLINK_NO_FOLLOW. + // - See the 3rd paragraph of + // "Symbolic link ownership, permissions, and timestamps" at: + // "http://man7.org/linux/man-pages/man7/symlink.7.html" + // - See the fchmodat() Linux man page: + // "http://man7.org/linux/man-pages/man2/fchmodat.2.html" +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) && \ + !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) && \ + !(defined(linux) || defined(__linux) || defined(__linux__)) && \ + !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) && \ + !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000) && \ + !(defined(__rtems__)) && \ + !(defined(__QNX__) && (_NTO_VERSION <= 700)) + if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms), !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW)) +#else // fallback if fchmodat() not supported + if (::chmod(p.c_str(), mode_cast(prms))) +#endif + { + const int err = errno; + if (!ec) + { + BOOST_FILESYSTEM_THROW(filesystem_error( + "boost::filesystem::permissions", p, error_code(err, system::generic_category()))); + } + + ec->assign(err, system::generic_category()); + } + +#else // Windows + + // if not going to alter FILE_ATTRIBUTE_READONLY, just return + if (!(!((prms & (add_perms | remove_perms))) || (prms & (owner_write | group_write | others_write)))) + return; + + DWORD attr = ::GetFileAttributesW(p.c_str()); + + if (error(attr == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions")) + return; + + if (prms & add_perms) + attr &= ~FILE_ATTRIBUTE_READONLY; + else if (prms & remove_perms) + attr |= FILE_ATTRIBUTE_READONLY; + else if (prms & (owner_write | group_write | others_write)) + attr &= ~FILE_ATTRIBUTE_READONLY; + else + attr |= FILE_ATTRIBUTE_READONLY; + + error(::SetFileAttributesW(p.c_str(), attr) == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::permissions"); +#endif +} + +BOOST_FILESYSTEM_DECL +path read_symlink(path const& p, system::error_code* ec) +{ + if (ec) + ec->clear(); + + path symlink_path; + +#ifdef BOOST_POSIX_API + const char* const path_str = p.c_str(); + char small_buf[small_path_size]; + ssize_t result = ::readlink(path_str, small_buf, sizeof(small_buf)); + if (BOOST_UNLIKELY(result < 0)) + { + fail: + const int err = errno; + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink", p, error_code(err, system_category()))); + + ec->assign(err, system_category()); + } + else if (BOOST_LIKELY(static_cast< std::size_t >(result) < sizeof(small_buf))) + { + symlink_path.assign(small_buf, small_buf + result); + } + else + { + for (std::size_t path_max = sizeof(small_buf) * 2u;; path_max *= 2u) // loop 'til buffer large enough + { + if (BOOST_UNLIKELY(path_max > absolute_path_max)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::read_symlink", p, error_code(ENAMETOOLONG, system_category()))); + + ec->assign(ENAMETOOLONG, system_category()); + break; + } + + boost::scoped_array< char > buf(new char[path_max]); + result = ::readlink(path_str, buf.get(), path_max); + if (BOOST_UNLIKELY(result < 0)) + { + goto fail; + } + else if (BOOST_LIKELY(static_cast< std::size_t >(result) < path_max)) + { + symlink_path.assign(buf.get(), buf.get() + result); + break; + } + } + } + +#else + + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + + DWORD error; + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + return_last_error: + error = ::GetLastError(); + emit_error(error, p, ec, "boost::filesystem::read_symlink"); + return symlink_path; + } + + boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new reparse_data_buffer_with_storage); + DWORD sz = 0u; + if (BOOST_UNLIKELY(!::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), sizeof(*buf), &sz, NULL))) + goto return_last_error; + + const wchar_t* buffer; + std::size_t offset, len; + switch (buf->rdb.ReparseTag) + { + case IO_REPARSE_TAG_MOUNT_POINT: + buffer = buf->rdb.MountPointReparseBuffer.PathBuffer; + offset = buf->rdb.MountPointReparseBuffer.SubstituteNameOffset; + len = buf->rdb.MountPointReparseBuffer.SubstituteNameLength; + break; + + case IO_REPARSE_TAG_SYMLINK: + buffer = buf->rdb.SymbolicLinkReparseBuffer.PathBuffer; + offset = buf->rdb.SymbolicLinkReparseBuffer.SubstituteNameOffset; + len = buf->rdb.SymbolicLinkReparseBuffer.SubstituteNameLength; + // Note: iff info.rdb.SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE + // -> resulting path is relative to the source + break; + + default: + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "Unknown ReparseTag in boost::filesystem::read_symlink"); + return symlink_path; + } + + symlink_path = convert_nt_path_to_win32_path(buffer + offset / sizeof(wchar_t), len / sizeof(wchar_t)); +#endif + + return symlink_path; +} + +BOOST_FILESYSTEM_DECL +path relative(path const& p, path const& base, error_code* ec) +{ + if (ec) + ec->clear(); + + error_code local_ec; + path cur_path; + if (!p.is_absolute() || !base.is_absolute()) + { + cur_path = detail::current_path(&local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + { + fail_local_ec: + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::relative", p, base, local_ec)); + + *ec = local_ec; + return path(); + } + } + + path wc_base(detail::weakly_canonical(base, cur_path, &local_ec)); + if (BOOST_UNLIKELY(!!local_ec)) + goto fail_local_ec; + path wc_p(detail::weakly_canonical(p, cur_path, &local_ec)); + if (BOOST_UNLIKELY(!!local_ec)) + goto fail_local_ec; + return wc_p.lexically_relative(wc_base); +} + +BOOST_FILESYSTEM_DECL +bool remove(path const& p, error_code* ec) +{ + if (ec) + ec->clear(); + + return detail::remove_impl(p, ec); +} + +BOOST_FILESYSTEM_DECL +uintmax_t remove_all(path const& p, error_code* ec) +{ + if (ec) + ec->clear(); + + return detail::remove_all_impl(p, ec); +} + +BOOST_FILESYSTEM_DECL +void rename(path const& old_p, path const& new_p, error_code* ec) +{ + error(!BOOST_MOVE_FILE(old_p.c_str(), new_p.c_str()) ? BOOST_ERRNO : 0, old_p, new_p, ec, "boost::filesystem::rename"); +} + +BOOST_FILESYSTEM_DECL +void resize_file(path const& p, uintmax_t size, system::error_code* ec) +{ +#if defined(BOOST_POSIX_API) + if (BOOST_UNLIKELY(size > static_cast< uintmax_t >((std::numeric_limits< off_t >::max)()))) + { + emit_error(system::errc::file_too_large, p, ec, "boost::filesystem::resize_file"); + return; + } +#endif + error(!BOOST_RESIZE_FILE(p.c_str(), size) ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::resize_file"); +} + +BOOST_FILESYSTEM_DECL +space_info space(path const& p, error_code* ec) +{ + space_info info; + // Initialize members to -1, as required by C++20 [fs.op.space]/1 in case of error + info.capacity = static_cast< uintmax_t >(-1); + info.free = static_cast< uintmax_t >(-1); + info.available = static_cast< uintmax_t >(-1); + + if (ec) + ec->clear(); + +#if defined(BOOST_FILESYSTEM_USE_WASI) + + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::space"); + +#elif defined(BOOST_POSIX_API) + + struct BOOST_STATVFS vfs; + if (!error(::BOOST_STATVFS(p.c_str(), &vfs) ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::space")) + { + info.capacity = static_cast< uintmax_t >(vfs.f_blocks) * BOOST_STATVFS_F_FRSIZE; + info.free = static_cast< uintmax_t >(vfs.f_bfree) * BOOST_STATVFS_F_FRSIZE; + info.available = static_cast< uintmax_t >(vfs.f_bavail) * BOOST_STATVFS_F_FRSIZE; + } + +#else + + // GetDiskFreeSpaceExW requires a directory path, which is unlike statvfs, which accepts any file. + // To work around this, test if the path refers to a directory and use the parent directory if not. + error_code local_ec; + file_status status = detail::status_impl(p, &local_ec); + if (status.type() == fs::status_error || status.type() == fs::file_not_found) + { + fail_local_ec: + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::space", p, local_ec)); + *ec = local_ec; + return info; + } + + path dir_path = p; + if (!is_directory(status)) + { + path cur_path = detail::current_path(ec); + if (ec && *ec) + return info; + + status = detail::symlink_status_impl(p, &local_ec); + if (status.type() == fs::status_error) + goto fail_local_ec; + if (is_symlink(status)) + { + // We need to resolve the symlink so that we report the space for the symlink target + dir_path = detail::canonical(p, cur_path, ec); + if (ec && *ec) + return info; + } + + dir_path = dir_path.parent_path(); + if (dir_path.empty()) + { + // The original path was just a filename, which is a relative path wrt. current directory + dir_path = cur_path; + } + } + + // For UNC names, the path must also include a trailing slash. + path::string_type str = dir_path.native(); + if (str.size() >= 2u && detail::is_directory_separator(str[0]) && detail::is_directory_separator(str[1]) && !detail::is_directory_separator(*(str.end() - 1))) + str.push_back(path::preferred_separator); + + ULARGE_INTEGER avail, total, free; + if (!error(::GetDiskFreeSpaceExW(str.c_str(), &avail, &total, &free) == 0, p, ec, "boost::filesystem::space")) + { + info.capacity = static_cast< uintmax_t >(total.QuadPart); + info.free = static_cast< uintmax_t >(free.QuadPart); + info.available = static_cast< uintmax_t >(avail.QuadPart); + } + +#endif + + return info; +} + +BOOST_FILESYSTEM_DECL +file_status status(path const& p, error_code* ec) +{ + if (ec) + ec->clear(); + + return detail::status_impl(p, ec); +} + +BOOST_FILESYSTEM_DECL +file_status symlink_status(path const& p, error_code* ec) +{ + if (ec) + ec->clear(); + + return detail::symlink_status_impl(p, ec); +} + +// contributed by Jeff Flinn +BOOST_FILESYSTEM_DECL +path temp_directory_path(system::error_code* ec) +{ + if (ec) + ec->clear(); + +#ifdef BOOST_POSIX_API + const char* val = NULL; + + (val = std::getenv("TMPDIR")) || + (val = std::getenv("TMP")) || + (val = std::getenv("TEMP")) || + (val = std::getenv("TEMPDIR")); + +#ifdef __ANDROID__ + const char* default_tmp = "/data/local/tmp"; +#else + const char* default_tmp = "/tmp"; +#endif + path p((val != NULL) ? val : default_tmp); + + if (BOOST_UNLIKELY(p.empty())) + { + fail_not_dir: + error(ENOTDIR, p, ec, "boost::filesystem::temp_directory_path"); + return p; + } + + file_status status = detail::status_impl(p, ec); + if (BOOST_UNLIKELY(ec && *ec)) + return path(); + if (BOOST_UNLIKELY(!is_directory(status))) + goto fail_not_dir; + + return p; + +#else // Windows +#if !defined(UNDER_CE) + + static const wchar_t* env_list[] = { L"TMP", L"TEMP", L"LOCALAPPDATA", L"USERPROFILE" }; + static const wchar_t temp_dir[] = L"Temp"; + + path p; + for (unsigned int i = 0; i < sizeof(env_list) / sizeof(*env_list); ++i) + { + std::wstring env = wgetenv(env_list[i]); + if (!env.empty()) + { + p = env; + if (i >= 2) + path_algorithms::append_v4(p, temp_dir, temp_dir + (sizeof(temp_dir) / sizeof(*temp_dir) - 1u)); + error_code lcl_ec; + if (exists(p, lcl_ec) && !lcl_ec && is_directory(p, lcl_ec) && !lcl_ec) + break; + p.clear(); + } + } + + if (p.empty()) + { + // use a separate buffer since in C++03 a string is not required to be contiguous + const UINT size = ::GetWindowsDirectoryW(NULL, 0); + if (BOOST_UNLIKELY(size == 0)) + { + getwindir_error: + int errval = ::GetLastError(); + error(errval, ec, "boost::filesystem::temp_directory_path"); + return path(); + } + + boost::scoped_array< wchar_t > buf(new wchar_t[size]); + if (BOOST_UNLIKELY(::GetWindowsDirectoryW(buf.get(), size) == 0)) + goto getwindir_error; + + p = buf.get(); // do not depend on initial buf size, see ticket #10388 + path_algorithms::append_v4(p, temp_dir, temp_dir + (sizeof(temp_dir) / sizeof(*temp_dir) - 1u)); + } + + return p; + +#else // Windows CE + + // Windows CE has no environment variables, so the same code as used for + // regular Windows, above, doesn't work. + + DWORD size = ::GetTempPathW(0, NULL); + if (size == 0u) + { + fail: + int errval = ::GetLastError(); + error(errval, ec, "boost::filesystem::temp_directory_path"); + return path(); + } + + boost::scoped_array< wchar_t > buf(new wchar_t[size]); + if (::GetTempPathW(size, buf.get()) == 0) + goto fail; + + path p(buf.get()); + p.remove_trailing_separator(); + + file_status status = detail::status_impl(p, ec); + if (ec && *ec) + return path(); + if (!is_directory(status)) + { + error(ERROR_PATH_NOT_FOUND, p, ec, "boost::filesystem::temp_directory_path"); + return path(); + } + + return p; + +#endif // !defined(UNDER_CE) +#endif +} + +BOOST_FILESYSTEM_DECL +path system_complete(path const& p, system::error_code* ec) +{ +#ifdef BOOST_POSIX_API + + if (p.empty() || p.is_absolute()) + return p; + + path res(current_path()); + path_algorithms::append_v4(res, p); + return res; + +#else + if (p.empty()) + { + if (ec) + ec->clear(); + return p; + } + + BOOST_CONSTEXPR_OR_CONST std::size_t buf_size = 128u; + wchar_t buf[buf_size]; + wchar_t* pfn; + std::size_t len = get_full_path_name(p, buf_size, buf, &pfn); + + if (error(len == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete")) + return path(); + + if (len < buf_size) // len does not include null termination character + return path(&buf[0]); + + boost::scoped_array< wchar_t > big_buf(new wchar_t[len]); + + return error(get_full_path_name(p, len, big_buf.get(), &pfn) == 0 ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::system_complete") ? path() : path(big_buf.get()); +#endif +} + +BOOST_FILESYSTEM_DECL +path weakly_canonical(path const& p, path const& base, system::error_code* ec) +{ + system::error_code local_ec; + const path::iterator p_end(p.end()); + +#if defined(BOOST_POSIX_API) + + path::iterator itr(p_end); + path head(p); + for (; !head.empty(); path_algorithms::decrement_v4(itr)) + { + file_status head_status(detail::status_impl(head, &local_ec)); + if (BOOST_UNLIKELY(head_status.type() == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::weakly_canonical", head, local_ec)); + + *ec = local_ec; + return path(); + } + + if (head_status.type() != fs::file_not_found) + break; + + head.remove_filename_and_trailing_separators(); + } + + if (head.empty()) + return path_algorithms::lexically_normal_v4(p); + + path const& dot_p = dot_path(); + path const& dot_dot_p = dot_dot_path(); + +#else + + // On Windows, filesystem APIs such as GetFileAttributesW and CreateFileW perform lexical path normalization + // internally. As a result, a path like "c:\a\.." can be reported as present even if "c:\a" is not. This would + // break canonical, as symlink_status that it calls internally would report an error that the file at the + // intermediate path does not exist. To avoid this, scan the initial path in the forward direction. + // Also, operate on paths with preferred separators. This can be important on Windows since GetFileAttributesW + // or CreateFileW, which is called in status() may return "file not found" for paths to network shares and + // mounted cloud storages that have forward slashes as separators. + // Also, avoid querying status of the root name such as \\?\c: as CreateFileW returns ERROR_INVALID_FUNCTION for + // such path. Querying the status of a root name such as c: is also not right as this path refers to the current + // directory on drive C:, which is not what we want to test for existence anyway. + path::iterator itr(p.begin()); + path head; + if (p.has_root_name()) + { + BOOST_ASSERT(itr != p_end); + head = *itr; + path_algorithms::increment_v4(itr); + } + + if (p.has_root_directory()) + { + BOOST_ASSERT(itr != p_end); + // Convert generic separator returned by the iterator for the root directory to + // the preferred separator. + head += path::preferred_separator; + path_algorithms::increment_v4(itr); + } + + if (!head.empty()) + { + file_status head_status(detail::status_impl(head, &local_ec)); + if (BOOST_UNLIKELY(head_status.type() == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::weakly_canonical", head, local_ec)); + + *ec = local_ec; + return path(); + } + + if (head_status.type() == fs::file_not_found) + { + // If the root path does not exist then no path element exists + return path_algorithms::lexically_normal_v4(p); + } + } + + path const& dot_p = dot_path(); + path const& dot_dot_p = dot_dot_path(); + for (; itr != p_end; path_algorithms::increment_v4(itr)) + { + path const& p_elem = *itr; + + // Avoid querying status of paths containing dot and dot-dot elements, as this will break + // if the root name starts with "\\?\". + if (path_algorithms::compare_v4(p_elem, dot_p) == 0) + continue; + + if (path_algorithms::compare_v4(p_elem, dot_dot_p) == 0) + { + if (head.has_relative_path()) + head.remove_filename_and_trailing_separators(); + + continue; + } + + path_algorithms::append_v4(head, p_elem); + + file_status head_status(detail::status_impl(head, &local_ec)); + if (BOOST_UNLIKELY(head_status.type() == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::weakly_canonical", head, local_ec)); + + *ec = local_ec; + return path(); + } + + if (head_status.type() == fs::file_not_found) + { + head.remove_filename_and_trailing_separators(); + break; + } + } + + if (head.empty()) + return path_algorithms::lexically_normal_v4(p); + +#endif + + path tail; + bool tail_has_dots = false; + for (; itr != p_end; path_algorithms::increment_v4(itr)) + { + path const& tail_elem = *itr; + path_algorithms::append_v4(tail, tail_elem); + // for a later optimization, track if any dot or dot-dot elements are present + if (!tail_has_dots && (path_algorithms::compare_v4(tail_elem, dot_p) == 0 || path_algorithms::compare_v4(tail_elem, dot_dot_p) == 0)) + tail_has_dots = true; + } + + head = detail::canonical(head, base, &local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::weakly_canonical", head, local_ec)); + + *ec = local_ec; + return path(); + } + + if (BOOST_LIKELY(!tail.empty())) + { + path_algorithms::append_v4(head, tail); + + // optimization: only normalize if tail had dot or dot-dot element + if (tail_has_dots) + return path_algorithms::lexically_normal_v4(head); + } + + return head; +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/path.cpp b/libs/filesystem/src/path.cpp new file mode 100644 index 0000000..1d9748c --- /dev/null +++ b/libs/filesystem/src/path.cpp @@ -0,0 +1,1633 @@ +// filesystem path.cpp ------------------------------------------------------------- // + +// Copyright Beman Dawes 2008 +// Copyright Andrey Semashev 2021-2023 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#include "platform_config.hpp" + +#include +#include +#include // codecvt_error_category() +#include +#include // for BOOST_SYSTEM_HAS_CONSTEXPR +#include +#include +#include +#include +#include +#include +#include +#include // std::atexit + +#ifdef BOOST_WINDOWS_API +#include "windows_file_codecvt.hpp" +#include "windows_tools.hpp" +#include +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) +#include +#endif + +#ifdef BOOST_FILESYSTEM_DEBUG +#include +#include +#endif + +#include "atomic_tools.hpp" +#include "private_config.hpp" + +#include // must be the last #include + +namespace fs = boost::filesystem; + +using boost::filesystem::path; + +//--------------------------------------------------------------------------------------// +// // +// class path helpers // +// // +//--------------------------------------------------------------------------------------// + +namespace { +//------------------------------------------------------------------------------------// +// miscellaneous class path helpers // +//------------------------------------------------------------------------------------// + +typedef path::value_type value_type; +typedef path::string_type string_type; +typedef string_type::size_type size_type; + +#ifdef BOOST_WINDOWS_API + +const wchar_t dot_path_literal[] = L"."; +const wchar_t dot_dot_path_literal[] = L".."; +const wchar_t separators[] = L"/\\"; +using boost::filesystem::detail::colon; +using boost::filesystem::detail::questionmark; + +inline bool is_alnum(wchar_t c) +{ + return boost::filesystem::detail::is_letter(c) || (c >= L'0' && c <= L'9'); +} + +inline bool is_device_name_char(wchar_t c) +{ + // https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html + // Device names are: + // + // - PRN + // - AUX + // - NUL + // - CON + // - LPT[1-9] + // - COM[1-9] + // - CONIN$ + // - CONOUT$ + return is_alnum(c) || c == L'$'; +} + +//! Returns position of the first directory separator in the \a size initial characters of \a p, or \a size if not found +inline size_type find_separator(const wchar_t* p, size_type size) BOOST_NOEXCEPT +{ + size_type pos = 0u; + for (; pos < size; ++pos) + { + const wchar_t c = p[pos]; + if (boost::filesystem::detail::is_directory_separator(c)) + break; + } + return pos; +} + +#else // BOOST_WINDOWS_API + +const char dot_path_literal[] = "."; +const char dot_dot_path_literal[] = ".."; +const char separators[] = "/"; + +//! Returns position of the first directory separator in the \a size initial characters of \a p, or \a size if not found +inline size_type find_separator(const char* p, size_type size) BOOST_NOEXCEPT +{ + const char* sep = static_cast< const char* >(std::memchr(p, '/', size)); + size_type pos = size; + if (BOOST_LIKELY(!!sep)) + pos = sep - p; + return pos; +} + +#endif // BOOST_WINDOWS_API + +// pos is position of the separator +bool is_root_separator(string_type const& str, size_type root_dir_pos, size_type pos); + +// Returns: Size of the filename element that ends at end_pos (which is past-the-end position). 0 if no filename found. +size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos); + +// Returns: starting position of root directory or size if not found. Sets root_name_size to length +// of the root name if the characters before the returned position (if any) are considered a root name. +size_type find_root_directory_start(const value_type* path, size_type size, size_type& root_name_size); + +// Finds position and size of the first element of the path +void first_element(string_type const& src, size_type& element_pos, size_type& element_size, size_type size); + +// Finds position and size of the first element of the path +inline void first_element(string_type const& src, size_type& element_pos, size_type& element_size) +{ + first_element(src, element_pos, element_size, src.size()); +} + +} // unnamed namespace + +//--------------------------------------------------------------------------------------// +// // +// class path implementation // +// // +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { +namespace detail { + +// C++14 provides a mismatch algorithm with four iterator arguments(), but earlier +// standard libraries didn't, so provide this needed functionality. +inline std::pair< path::iterator, path::iterator > mismatch(path::iterator it1, path::iterator it1end, path::iterator it2, path::iterator it2end) +{ + for (; it1 != it1end && it2 != it2end && path_algorithms::compare_v4(*it1, *it2) == 0;) + { + path_algorithms::increment_v4(it1); + path_algorithms::increment_v4(it2); + } + return std::make_pair(it1, it2); +} + +// normal --------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v3(path const& p) +{ + const value_type* const pathname = p.m_pathname.c_str(); + const size_type pathname_size = p.m_pathname.size(); + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size); + path normal(pathname, pathname + root_name_size); + +#if defined(BOOST_WINDOWS_API) + for (size_type i = 0; i < root_name_size; ++i) + { + if (normal.m_pathname[i] == path::separator) + normal.m_pathname[i] = path::preferred_separator; + } +#endif + + size_type root_path_size = root_name_size; + if (root_dir_pos < pathname_size) + { + root_path_size = root_dir_pos + 1; + normal.m_pathname.push_back(path::preferred_separator); + } + + size_type i = root_path_size; + + // Skip redundant directory separators after the root directory + while (i < pathname_size && detail::is_directory_separator(pathname[i])) + ++i; + + if (i < pathname_size) + { + bool last_element_was_dot = false; + while (true) + { + { + const size_type start_pos = i; + + // Find next separator + i += find_separator(pathname + i, pathname_size - i); + + const size_type size = i - start_pos; + + // Skip dot elements + if (size == 1u && pathname[start_pos] == path::dot) + { + last_element_was_dot = true; + goto skip_append; + } + + last_element_was_dot = false; + + // Process dot dot elements + if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size) + { + // Don't remove previous dot dot elements + const size_type normal_size = normal.m_pathname.size(); + size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size); + size_type pos = normal_size - filename_size; + if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot) + { + if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1])) + --pos; + normal.m_pathname.erase(normal.m_pathname.begin() + pos , normal.m_pathname.end()); + goto skip_append; + } + } + + // Append the element + path_algorithms::append_separator_if_needed(normal); + normal.m_pathname.append(pathname + start_pos, size); + } + + skip_append: + if (i == pathname_size) + break; + + // Skip directory separators, including duplicates + while (i < pathname_size && detail::is_directory_separator(pathname[i])) + ++i; + + if (i == pathname_size) + { + // If a path ends with a separator, add a trailing dot element + goto append_trailing_dot; + } + } + + if (normal.empty() || last_element_was_dot) + { + append_trailing_dot: + path_algorithms::append_separator_if_needed(normal); + normal.m_pathname.push_back(path::dot); + } + } + + return normal; +} + +BOOST_FILESYSTEM_DECL path path_algorithms::lexically_normal_v4(path const& p) +{ + const value_type* const pathname = p.m_pathname.c_str(); + const size_type pathname_size = p.m_pathname.size(); + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(pathname, pathname_size, root_name_size); + path normal(pathname, pathname + root_name_size); + +#if defined(BOOST_WINDOWS_API) + for (size_type i = 0; i < root_name_size; ++i) + { + if (normal.m_pathname[i] == path::separator) + normal.m_pathname[i] = path::preferred_separator; + } +#endif + + size_type root_path_size = root_name_size; + if (root_dir_pos < pathname_size) + { + root_path_size = root_dir_pos + 1; + normal.m_pathname.push_back(path::preferred_separator); + } + + size_type i = root_path_size; + + // Skip redundant directory separators after the root directory + while (i < pathname_size && detail::is_directory_separator(pathname[i])) + ++i; + + if (i < pathname_size) + { + while (true) + { + bool last_element_was_dot = false; + { + const size_type start_pos = i; + + // Find next separator + i += find_separator(pathname + i, pathname_size - i); + + const size_type size = i - start_pos; + + // Skip dot elements + if (size == 1u && pathname[start_pos] == path::dot) + { + last_element_was_dot = true; + goto skip_append; + } + + // Process dot dot elements + if (size == 2u && pathname[start_pos] == path::dot && pathname[start_pos + 1] == path::dot && normal.m_pathname.size() > root_path_size) + { + // Don't remove previous dot dot elements + const size_type normal_size = normal.m_pathname.size(); + size_type filename_size = find_filename_size(normal.m_pathname, root_path_size, normal_size); + size_type pos = normal_size - filename_size; + if (filename_size != 2u || normal.m_pathname[pos] != path::dot || normal.m_pathname[pos + 1] != path::dot) + { + if (pos > root_path_size && detail::is_directory_separator(normal.m_pathname[pos - 1])) + --pos; + normal.m_pathname.erase(normal.m_pathname.begin() + pos, normal.m_pathname.end()); + goto skip_append; + } + } + + // Append the element + path_algorithms::append_separator_if_needed(normal); + normal.m_pathname.append(pathname + start_pos, size); + } + + skip_append: + if (i == pathname_size) + { + // If a path ends with a trailing dot after a directory element, add a trailing separator + if (last_element_was_dot && !normal.empty() && !normal.filename_is_dot_dot()) + path_algorithms::append_separator_if_needed(normal); + + break; + } + + // Skip directory separators, including duplicates + while (i < pathname_size && detail::is_directory_separator(pathname[i])) + ++i; + + if (i == pathname_size) + { + // If a path ends with a separator, add a trailing separator + if (!normal.empty() && !normal.filename_is_dot_dot()) + path_algorithms::append_separator_if_needed(normal); + break; + } + } + + // If the original path was not empty and normalized ended up being empty, make it a dot + if (normal.empty()) + normal.m_pathname.push_back(path::dot); + } + + return normal; +} + +// append --------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL void path_algorithms::append_v3(path& p, const value_type* begin, const value_type* end) +{ + if (begin != end) + { + if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size()))) + { + if (!detail::is_directory_separator(*begin)) + path_algorithms::append_separator_if_needed(p); + p.m_pathname.append(begin, end); + } + else + { + // overlapping source + string_type rhs(begin, end); + path_algorithms::append_v3(p, rhs.data(), rhs.data() + rhs.size()); + } + } +} + +BOOST_FILESYSTEM_DECL void path_algorithms::append_v4(path& p, const value_type* begin, const value_type* end) +{ + if (begin != end) + { + if (BOOST_LIKELY(begin < p.m_pathname.data() || begin >= (p.m_pathname.data() + p.m_pathname.size()))) + { + const size_type that_size = end - begin; + size_type that_root_name_size = 0; + size_type that_root_dir_pos = find_root_directory_start(begin, that_size, that_root_name_size); + + // if (p.is_absolute()) + if + ( +#if defined(BOOST_WINDOWS_API) && !defined(UNDER_CE) + that_root_name_size > 0 && +#endif + that_root_dir_pos < that_size + ) + { + return_assign: + p.assign(begin, end); + return; + } + + size_type this_root_name_size = 0; + find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), this_root_name_size); + + if + ( + that_root_name_size > 0 && + (that_root_name_size != this_root_name_size || std::memcmp(p.m_pathname.c_str(), begin, this_root_name_size * sizeof(value_type)) != 0) + ) + { + goto return_assign; + } + + if (that_root_dir_pos < that_size) + { + // Remove root directory (if any) and relative path to replace with those from p + p.m_pathname.erase(p.m_pathname.begin() + this_root_name_size, p.m_pathname.end()); + } + + const value_type* const that_path = begin + that_root_name_size; + if (!detail::is_directory_separator(*that_path)) + path_algorithms::append_separator_if_needed(p); + p.m_pathname.append(that_path, end); + } + else + { + // overlapping source + string_type rhs(begin, end); + path_algorithms::append_v4(p, rhs.data(), rhs.data() + rhs.size()); + } + } + else if (path_algorithms::has_filename_v4(p)) + { + p.m_pathname.push_back(path::preferred_separator); + } +} + +// compare -------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v3 +( + path_detail::path_iterator first1, path_detail::path_iterator const& last1, + path_detail::path_iterator first2, path_detail::path_iterator const& last2 +) +{ + for (; first1 != last1 && first2 != last2;) + { + if (first1->native() < first2->native()) + return -1; + if (first2->native() < first1->native()) + return 1; + BOOST_ASSERT(first2->native() == first1->native()); + path_algorithms::increment_v3(first1); + path_algorithms::increment_v3(first2); + } + if (first1 == last1 && first2 == last2) + return 0; + return first1 == last1 ? -1 : 1; +} + +BOOST_FILESYSTEM_DECL int path_algorithms::lex_compare_v4 +( + path_detail::path_iterator first1, path_detail::path_iterator const& last1, + path_detail::path_iterator first2, path_detail::path_iterator const& last2 +) +{ + for (; first1 != last1 && first2 != last2;) + { + if (first1->native() < first2->native()) + return -1; + if (first2->native() < first1->native()) + return 1; + BOOST_ASSERT(first2->native() == first1->native()); + path_algorithms::increment_v4(first1); + path_algorithms::increment_v4(first2); + } + if (first1 == last1 && first2 == last2) + return 0; + return first1 == last1 ? -1 : 1; +} + +BOOST_FILESYSTEM_DECL int path_algorithms::compare_v3(path const& left, path const& right) +{ + return path_algorithms::lex_compare_v3(left.begin(), left.end(), right.begin(), right.end()); +} + +BOOST_FILESYSTEM_DECL int path_algorithms::compare_v4(path const& left, path const& right) +{ + return path_algorithms::lex_compare_v4(left.begin(), left.end(), right.begin(), right.end()); +} + +// append_separator_if_needed ------------------------------------------------------// + +BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::append_separator_if_needed(path& p) +{ + if (!p.m_pathname.empty() && +#ifdef BOOST_WINDOWS_API + *(p.m_pathname.end() - 1) != colon && +#endif + !detail::is_directory_separator(*(p.m_pathname.end() - 1))) + { + string_type::size_type tmp(p.m_pathname.size()); + p.m_pathname.push_back(path::preferred_separator); + return tmp; + } + return 0; +} + +// erase_redundant_separator -------------------------------------------------------// + +BOOST_FILESYSTEM_DECL void path_algorithms::erase_redundant_separator(path& p, string_type::size_type sep_pos) +{ + if (sep_pos // a separator was added + && sep_pos < p.m_pathname.size() // and something was appended + && (p.m_pathname[sep_pos + 1] == path::separator // and it was also separator +#ifdef BOOST_WINDOWS_API + || p.m_pathname[sep_pos + 1] == path::preferred_separator // or preferred_separator +#endif + )) + { + p.m_pathname.erase(p.m_pathname.begin() + sep_pos); // erase the added separator + } +} + +// modifiers -----------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v3(path& p) +{ + p.remove_filename_and_trailing_separators(); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::remove_filename_v4(path& p) +{ + size_type filename_size = path_algorithms::find_filename_v4_size(p); + p.m_pathname.erase(p.m_pathname.begin() + (p.m_pathname.size() - filename_size), p.m_pathname.end()); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v3(path& p, path const& new_extension) +{ + // erase existing extension, including the dot, if any + size_type ext_pos = p.m_pathname.size() - path_algorithms::extension_v3(p).m_pathname.size(); + p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end()); + + if (!new_extension.empty()) + { + // append new_extension, adding the dot if necessary + if (new_extension.m_pathname[0] != path::dot) + p.m_pathname.push_back(path::dot); + p.m_pathname.append(new_extension.m_pathname); + } +} + +BOOST_FILESYSTEM_DECL void path_algorithms::replace_extension_v4(path& p, path const& new_extension) +{ + // erase existing extension, including the dot, if any + size_type ext_pos = p.m_pathname.size() - path_algorithms::find_extension_v4_size(p); + p.m_pathname.erase(p.m_pathname.begin() + ext_pos, p.m_pathname.end()); + + if (!new_extension.empty()) + { + // append new_extension, adding the dot if necessary + if (new_extension.m_pathname[0] != path::dot) + p.m_pathname.push_back(path::dot); + p.m_pathname.append(new_extension.m_pathname); + } +} + +// decomposition -------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_name_size(path const& p) +{ + size_type root_name_size = 0; + find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size); + return root_name_size; +} + +BOOST_FILESYSTEM_DECL size_type path_algorithms::find_root_path_size(path const& p) +{ + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size); + + size_type size = root_name_size; + if (root_dir_pos < p.m_pathname.size()) + size = root_dir_pos + 1; + + return size; +} + +BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_root_directory(path const& p) +{ + substring root_dir; + size_type root_name_size = 0; + root_dir.pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size); + root_dir.size = static_cast< std::size_t >(root_dir.pos < p.m_pathname.size()); + return root_dir; +} + +BOOST_FILESYSTEM_DECL path_algorithms::substring path_algorithms::find_relative_path(path const& p) +{ + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), p.m_pathname.size(), root_name_size); + + // Skip root name, root directory and any duplicate separators + size_type size = root_name_size; + if (root_dir_pos < p.m_pathname.size()) + { + size = root_dir_pos + 1; + + for (size_type n = p.m_pathname.size(); size < n; ++size) + { + if (!detail::is_directory_separator(p.m_pathname[size])) + break; + } + } + + substring rel_path; + rel_path.pos = size; + rel_path.size = p.m_pathname.size() - size; + + return rel_path; +} + +BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_parent_path_size(path const& p) +{ + const size_type size = p.m_pathname.size(); + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size); + + size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size); + size_type end_pos = size - filename_size; + while (true) + { + if (end_pos <= root_name_size) + { + // Keep the root name as the parent path if there was a filename + if (filename_size == 0) + end_pos = 0u; + break; + } + + --end_pos; + + if (!detail::is_directory_separator(p.m_pathname[end_pos])) + { + ++end_pos; + break; + } + + if (end_pos == root_dir_pos) + { + // Keep the trailing root directory if there was a filename + end_pos += filename_size > 0; + break; + } + } + + return end_pos; +} + +BOOST_FILESYSTEM_DECL path path_algorithms::filename_v3(path const& p) +{ + const size_type size = p.m_pathname.size(); + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(p.m_pathname.c_str(), size, root_name_size); + size_type filename_size, pos; + if (root_dir_pos < size && detail::is_directory_separator(p.m_pathname[size - 1]) && is_root_separator(p.m_pathname, root_dir_pos, size - 1)) + { + // Return root directory + pos = root_dir_pos; + filename_size = 1u; + } + else if (root_name_size == size) + { + // Return root name + pos = 0u; + filename_size = root_name_size; + } + else + { + filename_size = find_filename_size(p.m_pathname, root_name_size, size); + pos = size - filename_size; + if (filename_size == 0u && pos > root_name_size && detail::is_directory_separator(p.m_pathname[pos - 1]) && !is_root_separator(p.m_pathname, root_dir_pos, pos - 1)) + return detail::dot_path(); + } + + const value_type* ptr = p.m_pathname.c_str() + pos; + return path(ptr, ptr + filename_size); +} + +BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_filename_v4_size(path const& p) +{ + const size_type size = p.m_pathname.size(); + size_type root_name_size = 0; + find_root_directory_start(p.m_pathname.c_str(), size, root_name_size); + return find_filename_size(p.m_pathname, root_name_size, size); +} + +BOOST_FILESYSTEM_DECL path path_algorithms::stem_v3(path const& p) +{ + path name(path_algorithms::filename_v3(p)); + if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0) + { + size_type pos = name.m_pathname.rfind(path::dot); + if (pos != string_type::npos) + name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end()); + } + return name; +} + +BOOST_FILESYSTEM_DECL path path_algorithms::stem_v4(path const& p) +{ + path name(path_algorithms::filename_v4(p)); + if (path_algorithms::compare_v4(name, detail::dot_path()) != 0 && path_algorithms::compare_v4(name, detail::dot_dot_path()) != 0) + { + size_type pos = name.m_pathname.rfind(path::dot); + if (pos != 0 && pos != string_type::npos) + name.m_pathname.erase(name.m_pathname.begin() + pos, name.m_pathname.end()); + } + return name; +} + +BOOST_FILESYSTEM_DECL path path_algorithms::extension_v3(path const& p) +{ + path name(path_algorithms::filename_v3(p)); + if (path_algorithms::compare_v4(name, detail::dot_path()) == 0 || path_algorithms::compare_v4(name, detail::dot_dot_path()) == 0) + return path(); + size_type pos(name.m_pathname.rfind(path::dot)); + return pos == string_type::npos ? path() : path(name.m_pathname.c_str() + pos); +} + +BOOST_FILESYSTEM_DECL path_algorithms::string_type::size_type path_algorithms::find_extension_v4_size(path const& p) +{ + const size_type size = p.m_pathname.size(); + size_type root_name_size = 0; + find_root_directory_start(p.m_pathname.c_str(), size, root_name_size); + size_type filename_size = find_filename_size(p.m_pathname, root_name_size, size); + size_type filename_pos = size - filename_size; + if + ( + filename_size > 0u && + // Check for "." and ".." filenames + !(p.m_pathname[filename_pos] == path::dot && + (filename_size == 1u || (filename_size == 2u && p.m_pathname[filename_pos + 1u] == path::dot))) + ) + { + size_type ext_pos = size; + while (ext_pos > filename_pos) + { + --ext_pos; + if (p.m_pathname[ext_pos] == path::dot) + break; + } + + if (ext_pos > filename_pos) + return size - ext_pos; + } + + return 0u; +} + +} // namespace detail + +BOOST_FILESYSTEM_DECL path& path::remove_filename_and_trailing_separators() +{ + size_type end_pos = detail::path_algorithms::find_parent_path_size(*this); + m_pathname.erase(m_pathname.begin() + end_pos, m_pathname.end()); + return *this; +} + +BOOST_FILESYSTEM_DECL path& path::remove_trailing_separator() +{ + if (!m_pathname.empty() && detail::is_directory_separator(m_pathname[m_pathname.size() - 1])) + m_pathname.erase(m_pathname.end() - 1); + return *this; +} + +BOOST_FILESYSTEM_DECL path& path::replace_filename(path const& replacement) +{ + detail::path_algorithms::remove_filename_v4(*this); + detail::path_algorithms::append_v4(*this, replacement.m_pathname.data(), replacement.m_pathname.data() + replacement.m_pathname.size()); + return *this; +} + +// lexical operations --------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL path path::lexically_relative(path const& base) const +{ + path::iterator b = begin(), e = end(), base_b = base.begin(), base_e = base.end(); + std::pair< path::iterator, path::iterator > mm = detail::mismatch(b, e, base_b, base_e); + if (mm.first == b && mm.second == base_b) + return path(); + if (mm.first == e && mm.second == base_e) + return detail::dot_path(); + + std::ptrdiff_t n = 0; + for (; mm.second != base_e; detail::path_algorithms::increment_v4(mm.second)) + { + path const& p = *mm.second; + if (detail::path_algorithms::compare_v4(p, detail::dot_dot_path()) == 0) + --n; + else if (!p.empty() && detail::path_algorithms::compare_v4(p, detail::dot_path()) != 0) + ++n; + } + if (n < 0) + return path(); + if (n == 0 && (mm.first == e || mm.first->empty())) + return detail::dot_path(); + + path tmp; + for (; n > 0; --n) + detail::path_algorithms::append_v4(tmp, detail::dot_dot_path()); + for (; mm.first != e; detail::path_algorithms::increment_v4(mm.first)) + detail::path_algorithms::append_v4(tmp, *mm.first); + return tmp; +} + +#if defined(BOOST_WINDOWS_API) + +BOOST_FILESYSTEM_DECL path path::generic_path() const +{ + path tmp(*this); + std::replace(tmp.m_pathname.begin(), tmp.m_pathname.end(), L'\\', L'/'); + return tmp; +} + +BOOST_FILESYSTEM_DECL path& path::make_preferred() +{ + std::replace(m_pathname.begin(), m_pathname.end(), L'/', L'\\'); + return *this; +} + +#endif // defined(BOOST_WINDOWS_API) + +} // namespace filesystem +} // namespace boost + +//--------------------------------------------------------------------------------------// +// // +// class path helpers implementation // +// // +//--------------------------------------------------------------------------------------// + +namespace { + +// is_root_separator ---------------------------------------------------------------// + +// pos is position of the separator +inline bool is_root_separator(string_type const& str, size_type root_dir_pos, size_type pos) +{ + BOOST_ASSERT_MSG(pos < str.size() && fs::detail::is_directory_separator(str[pos]), "precondition violation"); + + // root_dir_pos points at the leftmost separator, we need to skip any duplicate separators right of root dir + while (pos > root_dir_pos && fs::detail::is_directory_separator(str[pos - 1])) + --pos; + + return pos == root_dir_pos; +} + +// find_filename_size --------------------------------------------------------------// + +// Returns: Size of the filename element that ends at end_pos (which is past-the-end position). 0 if no filename found. +inline size_type find_filename_size(string_type const& str, size_type root_name_size, size_type end_pos) +{ + size_type pos = end_pos; + while (pos > root_name_size) + { + --pos; + + if (fs::detail::is_directory_separator(str[pos])) + { + ++pos; // filename starts past the separator + break; + } + } + + return end_pos - pos; +} + +// find_root_directory_start -------------------------------------------------------// + +// Returns: starting position of root directory or size if not found +size_type find_root_directory_start(const value_type* path, size_type size, size_type& root_name_size) +{ + root_name_size = 0; + if (size == 0) + return 0; + + bool parsing_root_name = false; + size_type pos = 0; + + // case "//", possibly followed by more characters + if (fs::detail::is_directory_separator(path[0])) + { + if (size >= 2 && fs::detail::is_directory_separator(path[1])) + { + if (size == 2) + { + // The whole path is just a pair of separators + root_name_size = 2; + return 2; + } +#ifdef BOOST_WINDOWS_API + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + // cases "\\?\" and "\\.\" + else if (size >= 4 && (path[2] == questionmark || path[2] == fs::path::dot) && fs::detail::is_directory_separator(path[3])) + { + parsing_root_name = true; + pos += 4; + } +#endif + else if (fs::detail::is_directory_separator(path[2])) + { + // The path starts with three directory separators, which is interpreted as a root directory followed by redundant separators + return 0; + } + else + { + // case "//net {/}" + parsing_root_name = true; + pos += 2; + goto find_next_separator; + } + } +#ifdef BOOST_WINDOWS_API + // https://stackoverflow.com/questions/23041983/path-prefixes-and + // case "\??\" (NT path prefix) + else if (size >= 4 && path[1] == questionmark && path[2] == questionmark && fs::detail::is_directory_separator(path[3])) + { + parsing_root_name = true; + pos += 4; + } +#endif + else + { + // The path starts with a separator, possibly followed by a non-separator character + return 0; + } + } + +#ifdef BOOST_WINDOWS_API + // case "c:" or "prn:" + // Note: There is ambiguity in a "c:x" path interpretation. It could either mean a file "x" located at the current directory for drive C:, + // or an alternative stream "x" of a file "c". Windows API resolve this as the former, and so do we. + if ((size - pos) >= 2 && fs::detail::is_letter(path[pos])) + { + size_type i = pos + 1; + for (; i < size; ++i) + { + if (!is_device_name_char(path[i])) + break; + } + + if (i < size && path[i] == colon) + { + pos = i + 1; + root_name_size = pos; + parsing_root_name = false; + + if (pos < size && fs::detail::is_directory_separator(path[pos])) + return pos; + } + } +#endif + + if (!parsing_root_name) + return size; + +find_next_separator: + pos += find_separator(path + pos, size - pos); + if (parsing_root_name) + root_name_size = pos; + + return pos; +} + +//--------------------------------------------------------------------------------------// +// // +// class path::iterator implementation // +// // +//--------------------------------------------------------------------------------------// + +// first_element ----------------------------------------------------------------------// + +// sets pos and len of first element, excluding extra separators +// if src.empty(), sets pos,len, to 0,0. +void first_element(string_type const& src, size_type& element_pos, size_type& element_size, size_type size) +{ + element_pos = 0; + element_size = 0; + if (src.empty()) + return; + + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(src.c_str(), size, root_name_size); + + // First element is the root name, if there is one + if (root_name_size > 0) + { + element_size = root_name_size; + return; + } + + // Otherwise, the root directory + if (root_dir_pos < size) + { + element_pos = root_dir_pos; + element_size = 1u; + return; + } + + // Otherwise, the first filename or directory name in a relative path + size_type end_pos = src.find_first_of(separators); + if (end_pos == string_type::npos) + end_pos = src.size(); + element_size = end_pos; +} + +} // unnamed namespace + +namespace boost { +namespace filesystem { +namespace detail { + +BOOST_FILESYSTEM_DECL void path_algorithms::increment_v3(path_detail::path_iterator& it) +{ + const size_type size = it.m_path_ptr->m_pathname.size(); + BOOST_ASSERT_MSG(it.m_pos < size, "path::iterator increment past end()"); + + // increment to position past current element; if current element is implicit dot, + // this will cause m_pos to represent the end iterator + it.m_pos += it.m_element.m_pathname.size(); + + // if the end is reached, we are done + if (it.m_pos >= size) + { + BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified"); + it.m_element.clear(); // aids debugging + return; + } + + // process separator (Windows drive spec is only case not a separator) + if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos])) + { + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size); + + // detect root directory and set iterator value to the separator if it is + if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size) + { + it.m_element.m_pathname = path::separator; // generic format; see docs + return; + } + + // skip separators until m_pos points to the start of the next element + while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos])) + { + ++it.m_pos; + } + + // detect trailing separator, and treat it as ".", per POSIX spec + if (it.m_pos == size && + !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1)) + { + --it.m_pos; + it.m_element = detail::dot_path(); + return; + } + } + + // get m_element + size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos); + if (end_pos == string_type::npos) + end_pos = size; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::increment_v4(path_detail::path_iterator& it) +{ + const size_type size = it.m_path_ptr->m_pathname.size(); + BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator increment past end()"); + + if (it.m_element.m_pathname.empty() && (it.m_pos + 1) == size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos])) + { + // The iterator was pointing to the last empty element of the path; set to end. + it.m_pos = size; + return; + } + + // increment to position past current element; if current element is implicit dot, + // this will cause m_pos to represent the end iterator + it.m_pos += it.m_element.m_pathname.size(); + + // if the end is reached, we are done + if (it.m_pos >= size) + { + BOOST_ASSERT_MSG(it.m_pos == size, "path::iterator increment after the referenced path was modified"); + it.m_element.clear(); // aids debugging + return; + } + + // process separator (Windows drive spec is only case not a separator) + if (detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos])) + { + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size); + + // detect root directory and set iterator value to the separator if it is + if (it.m_pos == root_dir_pos && it.m_element.m_pathname.size() == root_name_size) + { + it.m_element.m_pathname = path::separator; // generic format; see docs + return; + } + + // skip separators until m_pos points to the start of the next element + while (it.m_pos != size && detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos])) + { + ++it.m_pos; + } + + // detect trailing separator + if (it.m_pos == size && + !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1)) + { + --it.m_pos; + it.m_element.m_pathname.clear(); + return; + } + } + + // get m_element + size_type end_pos = it.m_path_ptr->m_pathname.find_first_of(separators, it.m_pos); + if (end_pos == string_type::npos) + end_pos = size; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v3(path_detail::path_iterator& it) +{ + const size_type size = it.m_path_ptr->m_pathname.size(); + BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()"); + BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified"); + + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size); + + if (root_dir_pos < size && it.m_pos == root_dir_pos) + { + // Was pointing at root directory, decrement to root name + set_to_root_name: + it.m_pos = 0u; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p, p + root_name_size); + return; + } + + // if at end and there was a trailing non-root '/', return "." + if (it.m_pos == size && + size > 1 && + detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) && + !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1)) + { + --it.m_pos; + it.m_element = detail::dot_path(); + return; + } + + // skip separators unless root directory + size_type end_pos = it.m_pos; + while (end_pos > root_name_size) + { + --end_pos; + + if (end_pos == root_dir_pos) + { + // Decremented to the root directory + it.m_pos = end_pos; + it.m_element.m_pathname = path::separator; // generic format; see docs + return; + } + + if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos])) + { + ++end_pos; + break; + } + } + + if (end_pos <= root_name_size) + goto set_to_root_name; + + size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos); + it.m_pos = end_pos - filename_size; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos); +} + +BOOST_FILESYSTEM_DECL void path_algorithms::decrement_v4(path_detail::path_iterator& it) +{ + const size_type size = it.m_path_ptr->m_pathname.size(); + BOOST_ASSERT_MSG(it.m_pos > 0, "path::iterator decrement past begin()"); + BOOST_ASSERT_MSG(it.m_pos <= size, "path::iterator decrement after the referenced path was modified"); + + size_type root_name_size = 0; + size_type root_dir_pos = find_root_directory_start(it.m_path_ptr->m_pathname.c_str(), size, root_name_size); + + if (root_dir_pos < size && it.m_pos == root_dir_pos) + { + // Was pointing at root directory, decrement to root name + set_to_root_name: + it.m_pos = 0u; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p, p + root_name_size); + return; + } + + // if at end and there was a trailing '/', return "" + if (it.m_pos == size && + size > 1 && + detail::is_directory_separator(it.m_path_ptr->m_pathname[it.m_pos - 1]) && + !is_root_separator(it.m_path_ptr->m_pathname, root_dir_pos, it.m_pos - 1)) + { + --it.m_pos; + it.m_element.m_pathname.clear(); + return; + } + + // skip separators unless root directory + size_type end_pos = it.m_pos; + while (end_pos > root_name_size) + { + --end_pos; + + if (end_pos == root_dir_pos) + { + // Decremented to the root directory + it.m_pos = end_pos; + it.m_element.m_pathname = path::separator; // generic format; see docs + return; + } + + if (!detail::is_directory_separator(it.m_path_ptr->m_pathname[end_pos])) + { + ++end_pos; + break; + } + } + + if (end_pos <= root_name_size) + goto set_to_root_name; + + size_type filename_size = find_filename_size(it.m_path_ptr->m_pathname, root_name_size, end_pos); + it.m_pos = end_pos - filename_size; + const path::value_type* p = it.m_path_ptr->m_pathname.c_str(); + it.m_element.m_pathname.assign(p + it.m_pos, p + end_pos); +} + +} // namespace detail + +// path iterators ------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL path::iterator path::begin() const +{ + iterator itr; + itr.m_path_ptr = this; + + size_type element_size; + first_element(m_pathname, itr.m_pos, element_size); + + if (element_size > 0) + { + itr.m_element = m_pathname.substr(itr.m_pos, element_size); +#ifdef BOOST_WINDOWS_API + if (itr.m_element.m_pathname.size() == 1u && itr.m_element.m_pathname[0] == path::preferred_separator) + itr.m_element.m_pathname[0] = path::separator; +#endif + } + + return itr; +} + +BOOST_FILESYSTEM_DECL path::iterator path::end() const +{ + iterator itr; + itr.m_path_ptr = this; + itr.m_pos = m_pathname.size(); + return itr; +} + +} // namespace filesystem +} // namespace boost + +namespace { + +//------------------------------------------------------------------------------------// +// locale helpers // +//------------------------------------------------------------------------------------// + +// Prior versions of these locale and codecvt implementations tried to take advantage +// of static initialization where possible, kept a local copy of the current codecvt +// facet (to avoid codecvt() having to call use_facet()), and was not multi-threading +// safe (again for efficiency). +// +// This was error prone, and required different implementation techniques depending +// on the compiler and also whether static or dynamic linking was used. Furthermore, +// users could not easily provide their multi-threading safe wrappers because the +// path interface requires the implementation itself to call codecvt() to obtain the +// default facet, and the initialization of the static within path_locale() could race. +// +// The code below is portable to all platforms, is much simpler, and hopefully will be +// much more robust. Timing tests (on Windows, using a Visual C++ release build) +// indicated the current code is roughly 9% slower than the previous code, and that +// seems a small price to pay for better code that is easier to use. + +std::locale default_locale() +{ +#if defined(BOOST_WINDOWS_API) + std::locale global_loc = std::locale(); + return std::locale(global_loc, new boost::filesystem::detail::windows_file_codecvt()); +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__HAIKU__) + // "All BSD system functions expect their string parameters to be in UTF-8 encoding + // and nothing else." See + // http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPInternational/Articles/FileEncodings.html + // + // "The kernel will reject any filename that is not a valid UTF-8 string, and it will + // even be normalized (to Unicode NFD) before stored on disk, at least when using HFS. + // The right way to deal with it would be to always convert the filename to UTF-8 + // before trying to open/create a file." See + // http://lists.apple.com/archives/unix-porting/2007/Sep/msg00023.html + // + // "How a file name looks at the API level depends on the API. Current Carbon APIs + // handle file names as an array of UTF-16 characters; POSIX ones handle them as an + // array of UTF-8, which is why UTF-8 works well in Terminal. How it's stored on disk + // depends on the disk format; HFS+ uses UTF-16, but that's not important in most + // cases." See + // http://lists.apple.com/archives/applescript-users/2002/Sep/msg00319.html + // + // Many thanks to Peter Dimov for digging out the above references! + + std::locale global_loc = std::locale(); + return std::locale(global_loc, new boost::filesystem::detail::utf8_codecvt_facet()); +#else // Other POSIX + // ISO C calls std::locale("") "the locale-specific native environment", and this + // locale is the default for many POSIX-based operating systems such as Linux. + return std::locale(""); +#endif +} + +std::locale* g_path_locale = NULL; + +void schedule_path_locale_cleanup() BOOST_NOEXCEPT; + +// std::locale("") construction, needed on non-Apple POSIX systems, can throw +// (if environmental variables LC_MESSAGES or LANG are wrong, for example), so +// get_path_locale() provides lazy initialization to ensure that any +// exceptions occur after main() starts and so can be caught. Furthermore, +// g_path_locale is only initialized if path::codecvt() or path::imbue() are themselves +// actually called, ensuring that an exception will only be thrown if std::locale("") +// is really needed. +inline std::locale& get_path_locale() +{ +#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + atomic_ns::atomic_ref< std::locale* > a(g_path_locale); + std::locale* p = a.load(atomic_ns::memory_order_acquire); + if (BOOST_UNLIKELY(!p)) + { + std::locale* new_p = new std::locale(default_locale()); + if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire)) + { + p = new_p; + schedule_path_locale_cleanup(); + } + else + { + delete new_p; + } + } + return *p; +#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + std::locale* p = g_path_locale; + if (BOOST_UNLIKELY(!p)) + { + g_path_locale = p = new std::locale(default_locale()); + schedule_path_locale_cleanup(); + } + return *p; +#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) +} + +inline std::locale* replace_path_locale(std::locale const& loc) +{ + std::locale* new_p = new std::locale(loc); +#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + std::locale* p = atomic_ns::atomic_ref< std::locale* >(g_path_locale).exchange(new_p, atomic_ns::memory_order_acq_rel); +#else + std::locale* p = g_path_locale; + g_path_locale = new_p; +#endif + if (!p) + schedule_path_locale_cleanup(); + return p; +} + +#if defined(_MSC_VER) + +const boost::filesystem::path* g_dot_path = NULL; +const boost::filesystem::path* g_dot_dot_path = NULL; + +inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT +{ +} + +inline boost::filesystem::path const& get_dot_path() +{ +#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + atomic_ns::atomic_ref< const boost::filesystem::path* > a(g_dot_path); + const boost::filesystem::path* p = a.load(atomic_ns::memory_order_acquire); + if (BOOST_UNLIKELY(!p)) + { + const boost::filesystem::path* new_p = new boost::filesystem::path(dot_path_literal); + if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire)) + p = new_p; + else + delete new_p; + } + return *p; +#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + const boost::filesystem::path* p = g_dot_path; + if (BOOST_UNLIKELY(!p)) + g_dot_path = p = new boost::filesystem::path(dot_path_literal); + return *p; +#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) +} + +inline boost::filesystem::path const& get_dot_dot_path() +{ +#if !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + atomic_ns::atomic_ref< const boost::filesystem::path* > a(g_dot_dot_path); + const boost::filesystem::path* p = a.load(atomic_ns::memory_order_acquire); + if (BOOST_UNLIKELY(!p)) + { + const boost::filesystem::path* new_p = new boost::filesystem::path(dot_dot_path_literal); + if (a.compare_exchange_strong(p, new_p, atomic_ns::memory_order_acq_rel, atomic_ns::memory_order_acquire)) + p = new_p; + else + delete new_p; + } + return *p; +#else // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) + const boost::filesystem::path* p = g_dot_dot_path; + if (BOOST_UNLIKELY(!p)) + g_dot_dot_path = p = new boost::filesystem::path(dot_dot_path_literal); + return *p; +#endif // !defined(BOOST_FILESYSTEM_SINGLE_THREADED) +} + +void __cdecl destroy_path_globals() +{ + delete g_dot_dot_path; + g_dot_dot_path = NULL; + delete g_dot_path; + g_dot_path = NULL; + delete g_path_locale; + g_path_locale = NULL; +} + +BOOST_FILESYSTEM_INIT_FUNC init_path_globals() +{ +#if !defined(BOOST_SYSTEM_HAS_CONSTEXPR) + // codecvt_error_category needs to be called early to dynamic-initialize the error category instance + boost::filesystem::codecvt_error_category(); +#endif + std::atexit(&destroy_path_globals); + return BOOST_FILESYSTEM_INITRETSUCCESS_V; +} + +#if _MSC_VER >= 1400 + +#pragma section(".CRT$XCM", long, read) +__declspec(allocate(".CRT$XCM")) BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +extern const init_func_ptr_t p_init_path_globals = &init_path_globals; + +#else // _MSC_VER >= 1400 + +#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +#pragma data_seg(push, old_seg) +#endif +#pragma data_seg(".CRT$XCM") +BOOST_ATTRIBUTE_UNUSED BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +extern const init_func_ptr_t p_init_path_globals = &init_path_globals; +#pragma data_seg() +#if (_MSC_VER >= 1300) // 1300 == VC++ 7.0 +#pragma data_seg(pop, old_seg) +#endif + +#endif // _MSC_VER >= 1400 + +#if defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN) +//! Makes sure the global initializer pointers are referenced and not removed by linker +struct globals_retainer +{ + const init_func_ptr_t* volatile m_p_init_path_globals; + + globals_retainer() { m_p_init_path_globals = &p_init_path_globals; } +}; +BOOST_ATTRIBUTE_UNUSED +static const globals_retainer g_globals_retainer; +#endif // defined(BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN) + +#else // defined(_MSC_VER) + +struct path_locale_deleter +{ + ~path_locale_deleter() + { + delete g_path_locale; + g_path_locale = NULL; + } +}; + +#if defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) + +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY) BOOST_ATTRIBUTE_UNUSED +const path_locale_deleter g_path_locale_deleter = {}; +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY) +const boost::filesystem::path g_dot_path(dot_path_literal); +BOOST_FILESYSTEM_INIT_PRIORITY(BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY) +const boost::filesystem::path g_dot_dot_path(dot_dot_path_literal); + +inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT +{ +} + +inline boost::filesystem::path const& get_dot_path() +{ + return g_dot_path; +} + +inline boost::filesystem::path const& get_dot_dot_path() +{ + return g_dot_dot_path; +} + +#else // defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) + +inline void schedule_path_locale_cleanup() BOOST_NOEXCEPT +{ + BOOST_ATTRIBUTE_UNUSED static const path_locale_deleter g_path_locale_deleter; +} + +inline boost::filesystem::path const& get_dot_path() +{ + static const boost::filesystem::path g_dot_path(dot_path_literal); + return g_dot_path; +} + +inline boost::filesystem::path const& get_dot_dot_path() +{ + static const boost::filesystem::path g_dot_dot_path(dot_dot_path_literal); + return g_dot_dot_path; +} + +#endif // defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) + +#endif // defined(_MSC_VER) + +} // unnamed namespace + +//--------------------------------------------------------------------------------------// +// path::codecvt() and path::imbue() implementation // +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { + +BOOST_FILESYSTEM_DECL path::codecvt_type const& path::codecvt() +{ +#ifdef BOOST_FILESYSTEM_DEBUG + std::cout << "***** path::codecvt() called" << std::endl; +#endif + return std::use_facet< std::codecvt< wchar_t, char, std::mbstate_t > >(get_path_locale()); +} + +BOOST_FILESYSTEM_DECL std::locale path::imbue(std::locale const& loc) +{ +#ifdef BOOST_FILESYSTEM_DEBUG + std::cout << "***** path::imbue() called" << std::endl; +#endif + std::locale* p = replace_path_locale(loc); + if (BOOST_LIKELY(p != NULL)) + { + // Note: copying/moving std::locale does not throw +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + std::locale temp(std::move(*p)); +#else + std::locale temp(*p); +#endif + delete p; + return temp; + } + + return default_locale(); +} + +namespace detail { + +BOOST_FILESYSTEM_DECL path const& dot_path() +{ + return get_dot_path(); +} + +BOOST_FILESYSTEM_DECL path const& dot_dot_path() +{ + return get_dot_dot_path(); +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/path_traits.cpp b/libs/filesystem/src/path_traits.cpp new file mode 100644 index 0000000..baed387 --- /dev/null +++ b/libs/filesystem/src/path_traits.cpp @@ -0,0 +1,187 @@ +// filesystem path_traits.cpp --------------------------------------------------------// + +// Copyright Beman Dawes 2008, 2009 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include // for codecvt_base::result +#include // for mbstate_t +#include + +#include // must be the last #include + +namespace pt = boost::filesystem::detail::path_traits; +namespace fs = boost::filesystem; +namespace bs = boost::system; + +//--------------------------------------------------------------------------------------// +// configuration // +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_CODECVT_BUF_SIZE +#define BOOST_FILESYSTEM_CODECVT_BUF_SIZE 256 +#endif + +namespace { + +BOOST_CONSTEXPR_OR_CONST std::size_t default_codecvt_buf_size = BOOST_FILESYSTEM_CODECVT_BUF_SIZE; + +//--------------------------------------------------------------------------------------// +// // +// The public convert() functions do buffer management, and then forward to the // +// convert_aux() functions for the actual call to the codecvt facet. // +// // +//--------------------------------------------------------------------------------------// + +//--------------------------------------------------------------------------------------// +// convert_aux const char* to wstring // +//--------------------------------------------------------------------------------------// + +void convert_aux(const char* from, const char* from_end, wchar_t* to, wchar_t* to_end, std::wstring& target, pt::codecvt_type const& cvt) +{ + //std::cout << std::hex + // << " from=" << std::size_t(from) + // << " from_end=" << std::size_t(from_end) + // << " to=" << std::size_t(to) + // << " to_end=" << std::size_t(to_end) + // << std::endl; + + std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports + const char* from_next; + wchar_t* to_next; + + std::codecvt_base::result res; + + if ((res = cvt.in(state, from, from_end, from_next, to, to_end, to_next)) != std::codecvt_base::ok) + { + //std::cout << " result is " << static_cast(res) << std::endl; + BOOST_FILESYSTEM_THROW(bs::system_error(res, fs::codecvt_error_category(), "boost::filesystem::path codecvt to wstring")); + } + target.append(to, to_next); +} + +//--------------------------------------------------------------------------------------// +// convert_aux const wchar_t* to string // +//--------------------------------------------------------------------------------------// + +void convert_aux(const wchar_t* from, const wchar_t* from_end, char* to, char* to_end, std::string& target, pt::codecvt_type const& cvt) +{ + //std::cout << std::hex + // << " from=" << std::size_t(from) + // << " from_end=" << std::size_t(from_end) + // << " to=" << std::size_t(to) + // << " to_end=" << std::size_t(to_end) + // << std::endl; + + std::mbstate_t state = std::mbstate_t(); // perhaps unneeded, but cuts bug reports + const wchar_t* from_next; + char* to_next; + + std::codecvt_base::result res; + + if ((res = cvt.out(state, from, from_end, from_next, to, to_end, to_next)) != std::codecvt_base::ok) + { + //std::cout << " result is " << static_cast(res) << std::endl; + BOOST_FILESYSTEM_THROW(bs::system_error(res, fs::codecvt_error_category(), "boost::filesystem::path codecvt to string")); + } + target.append(to, to_next); +} + +} // unnamed namespace + +//--------------------------------------------------------------------------------------// +// path_traits // +//--------------------------------------------------------------------------------------// + +namespace boost { +namespace filesystem { +namespace detail { +namespace path_traits { + +//--------------------------------------------------------------------------------------// +// convert const char* to wstring // +//--------------------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL +void convert(const char* from, const char* from_end, std::wstring& to, const codecvt_type* cvt) +{ + if (from == from_end) + return; + + BOOST_ASSERT(from != NULL); + BOOST_ASSERT(from_end != NULL); + + if (!cvt) + cvt = &fs::path::codecvt(); + + std::size_t buf_size = (from_end - from) * 3; // perhaps too large, but that's OK + + // dynamically allocate a buffer only if source is unusually large + if (buf_size > default_codecvt_buf_size) + { + boost::scoped_array< wchar_t > buf(new wchar_t[buf_size]); + convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, *cvt); + } + else + { + wchar_t buf[default_codecvt_buf_size]; + convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, *cvt); + } +} + +//--------------------------------------------------------------------------------------// +// convert const wchar_t* to string // +//--------------------------------------------------------------------------------------// + +BOOST_FILESYSTEM_DECL +void convert(const wchar_t* from, const wchar_t* from_end, std::string& to, const codecvt_type* cvt) +{ + if (from == from_end) + return; + + BOOST_ASSERT(from != NULL); + BOOST_ASSERT(from_end != NULL); + + if (!cvt) + cvt = &fs::path::codecvt(); + + // The codecvt length functions may not be implemented, and I don't really + // understand them either. Thus this code is just a guess; if it turns + // out the buffer is too small then an error will be reported and the code + // will have to be fixed. + std::size_t buf_size = (from_end - from) * 4; // perhaps too large, but that's OK + buf_size += 4; // encodings like shift-JIS need some prefix space + + // dynamically allocate a buffer only if source is unusually large + if (buf_size > default_codecvt_buf_size) + { + boost::scoped_array< char > buf(new char[buf_size]); + convert_aux(from, from_end, buf.get(), buf.get() + buf_size, to, *cvt); + } + else + { + char buf[default_codecvt_buf_size]; + convert_aux(from, from_end, buf, buf + default_codecvt_buf_size, to, *cvt); + } +} + +} // namespace path_traits +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/platform_config.hpp b/libs/filesystem/src/platform_config.hpp new file mode 100644 index 0000000..941338b --- /dev/null +++ b/libs/filesystem/src/platform_config.hpp @@ -0,0 +1,83 @@ +// platform_config.hpp --------------------------------------------------------------------// + +// Copyright 2020 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +#ifndef BOOST_FILESYSTEM_PLATFORM_CONFIG_HPP_ +#define BOOST_FILESYSTEM_PLATFORM_CONFIG_HPP_ + +// define 64-bit offset macros BEFORE including boost/config.hpp (see ticket #5355) +#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 24 +// Android fully supports 64-bit file offsets only for API 24 and above. +// +// Trying to define _FILE_OFFSET_BITS=64 for APIs below 24 +// leads to compilation failure for one or another reason, +// depending on target Android API level, Android NDK version, +// used STL, order of include paths and more. +// For more information, please see: +// - https://github.com/boostorg/filesystem/issues/65 +// - https://github.com/boostorg/filesystem/pull/69 +// +// Android NDK developers consider it the expected behavior. +// See their official position here: +// - https://github.com/android-ndk/ndk/issues/501#issuecomment-326447479 +// - https://android.googlesource.com/platform/bionic/+/a34817457feee026e8702a1d2dffe9e92b51d7d1/docs/32-bit-abi.md#32_bit-abi-bugs +// +// Thus we do not define _FILE_OFFSET_BITS in such case. +#else +// Defining _FILE_OFFSET_BITS=64 should kick in 64-bit off_t's +// (and thus st_size) on 32-bit systems that provide the Large File +// Support (LFS) interface, such as Linux, Solaris, and IRIX. +// +// At the time of this comment writing (March 2018), on most systems +// _FILE_OFFSET_BITS=64 definition is harmless: +// either the definition is supported and enables 64-bit off_t, +// or the definition is not supported and is ignored, in which case +// off_t does not change its default size for the target system +// (which may be 32-bit or 64-bit already). +// Thus it makes sense to have _FILE_OFFSET_BITS=64 defined by default, +// instead of listing every system that supports the definition. +// Those few systems, on which _FILE_OFFSET_BITS=64 is harmful, +// for example this definition causes compilation failure on those systems, +// should be exempt from defining _FILE_OFFSET_BITS by adding +// an appropriate #elif block above with the appropriate comment. +// +// _FILE_OFFSET_BITS must be defined before any headers are included +// to ensure that the definition is available to all included headers. +// That is required at least on Solaris, and possibly on other +// systems as well. +#define _FILE_OFFSET_BITS 64 +#endif + +#if defined(__APPLE__) || defined(__MACH__) +// Enable newer ABI on Mac OS 10.5 and later, which is needed for struct stat to have birthtime members +#define _DARWIN_USE_64_BIT_INODE 1 +#endif + +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS // Sun readdir_r() needs this +#endif + +#if !defined(_INCLUDE_STDCSOURCE_199901) && (defined(hpux) || defined(_hpux) || defined(__hpux)) +// For HP-UX, request that WCHAR_MAX and WCHAR_MIN be defined as macros, +// not casts. See ticket 5048 +#define _INCLUDE_STDCSOURCE_199901 +#endif + +#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) || \ + defined(__CYGWIN__) +// Define target Windows version macros before including any other headers +#include +#endif + +#ifndef BOOST_SYSTEM_NO_DEPRECATED +#define BOOST_SYSTEM_NO_DEPRECATED +#endif + +#include + +#endif // BOOST_FILESYSTEM_PLATFORM_CONFIG_HPP_ diff --git a/libs/filesystem/src/portability.cpp b/libs/filesystem/src/portability.cpp new file mode 100644 index 0000000..8e0e2e5 --- /dev/null +++ b/libs/filesystem/src/portability.cpp @@ -0,0 +1,83 @@ +// portability.cpp -------------------------------------------------------------------// + +// Copyright 2002-2005 Beman Dawes +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include +#include + +#include // SGI MIPSpro compilers need this +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { + +namespace { + +BOOST_CONSTEXPR_OR_CONST char windows_invalid_chars[] = + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + "<>:\"/\\|"; + +BOOST_CONSTEXPR_OR_CONST char posix_valid_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-"; + +} // unnamed namespace + +// name_check functions ----------------------------------------------// + +#ifdef BOOST_WINDOWS +BOOST_FILESYSTEM_DECL bool native(std::string const& name) +{ + return windows_name(name); +} +#else +BOOST_FILESYSTEM_DECL bool native(std::string const& name) +{ + return !name.empty() && name[0] != ' ' && name.find('/') == std::string::npos; +} +#endif + +BOOST_FILESYSTEM_DECL bool portable_posix_name(std::string const& name) +{ + return !name.empty() && name.find_first_not_of(posix_valid_chars, 0, sizeof(posix_valid_chars) - 1) == std::string::npos; +} + +BOOST_FILESYSTEM_DECL bool windows_name(std::string const& name) +{ + // note that the terminating '\0' is part of the string - thus the size below + // is sizeof(windows_invalid_chars) rather than sizeof(windows_invalid_chars)-1. + return !name.empty() && name[0] != ' ' && name.find_first_of(windows_invalid_chars, 0, sizeof(windows_invalid_chars)) == std::string::npos + && *(name.end() - 1) != ' ' && (*(name.end() - 1) != '.' || name.size() == 1 || name == ".."); +} + +BOOST_FILESYSTEM_DECL bool portable_name(std::string const& name) +{ + return !name.empty() && (name == "." || name == ".." || (windows_name(name) && portable_posix_name(name) && name[0] != '.' && name[0] != '-')); +} + +BOOST_FILESYSTEM_DECL bool portable_directory_name(std::string const& name) +{ + return name == "." || name == ".." || (portable_name(name) && name.find('.') == std::string::npos); +} + +BOOST_FILESYSTEM_DECL bool portable_file_name(std::string const& name) +{ + std::string::size_type pos; + return portable_name(name) && name != "." && name != ".." && ((pos = name.find('.')) == std::string::npos || (name.find('.', pos + 1) == std::string::npos && (pos + 5) > name.size())); +} + +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/posix_tools.hpp b/libs/filesystem/src/posix_tools.hpp new file mode 100644 index 0000000..52cd87b --- /dev/null +++ b/libs/filesystem/src/posix_tools.hpp @@ -0,0 +1,81 @@ +// posix_tools.hpp -------------------------------------------------------------------// + +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_POSIX_TOOLS_HPP_ +#define BOOST_FILESYSTEM_SRC_POSIX_TOOLS_HPP_ + +#include "platform_config.hpp" +#include +#include +#ifdef BOOST_HAS_UNISTD_H +#include +#endif + +#include // must be the last #include + +namespace boost { +namespace filesystem { +namespace detail { + +//! Platform-specific parameters for directory iterator construction +struct directory_iterator_params +{ +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + //! File descriptor of the base directory relative to which to interpret relative paths + int basedir_fd; +#endif +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + //! File descriptor of the directory over which the iterator iterates + int iterator_fd; +#endif +}; + +/*! + * Closes a file descriptor and returns the result, similar to close(2). Unlike close(2), guarantees that the file descriptor is closed even if EINTR error happens. + * + * Some systems don't close the file descriptor in case if the thread is interrupted by a signal and close(2) returns EINTR. + * Other (most) systems do close the file descriptor even when when close(2) returns EINTR, and attempting to close it + * again could close a different file descriptor that was opened by a different thread. This function hides this difference in behavior. + * + * Future POSIX standards will likely fix this by introducing posix_close (see https://www.austingroupbugs.net/view.php?id=529) + * and prohibiting returning EINTR from close(2), but we still have to support older systems where this new behavior is not available and close(2) + * behaves differently between systems. + */ +inline int close_fd(int fd) +{ +#if defined(hpux) || defined(_hpux) || defined(__hpux) + int res; + while (true) + { + res = ::close(fd); + if (BOOST_UNLIKELY(res < 0)) + { + int err = errno; + if (err == EINTR) + continue; + } + + break; + } + + return res; +#else + return ::close(fd); +#endif +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_SRC_POSIX_TOOLS_HPP_ diff --git a/libs/filesystem/src/private_config.hpp b/libs/filesystem/src/private_config.hpp new file mode 100644 index 0000000..c58d245 --- /dev/null +++ b/libs/filesystem/src/private_config.hpp @@ -0,0 +1,74 @@ +// private_config.hpp ----------------------------------------------------------------// + +// Copyright 2021 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_PRIVATE_CONFIG_HPP_ +#define BOOST_FILESYSTEM_SRC_PRIVATE_CONFIG_HPP_ + +#include + +#if defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) +#define BOOST_FILESYSTEM_INIT_PRIORITY(n) __attribute__ ((init_priority(n))) +#else +#define BOOST_FILESYSTEM_INIT_PRIORITY(n) +#endif + +// According to https://gcc.gnu.org/bugzilla//show_bug.cgi?id=65115, +// the default C++ object initializers priority is 65535. We would like to +// initialize function pointers earlier than that (with lower priority values), +// before the other global objects initializers are run. Other than this, +// these priority values are arbitrary. +#define BOOST_FILESYSTEM_FUNC_PTR_INIT_PRIORITY 32767 + +// Path globals initialization priority +#define BOOST_FILESYSTEM_PATH_GLOBALS_INIT_PRIORITY 32768 + +#if defined(__has_feature) && defined(__has_attribute) +#if __has_feature(memory_sanitizer) && __has_attribute(no_sanitize) +#define BOOST_FILESYSTEM_NO_SANITIZE_MEMORY __attribute__ ((no_sanitize("memory"))) +#endif +#endif // defined(__has_feature) && defined(__has_attribute) + +#ifndef BOOST_FILESYSTEM_NO_SANITIZE_MEMORY +#define BOOST_FILESYSTEM_NO_SANITIZE_MEMORY +#endif + +#if defined(_MSC_VER) +#if _MSC_VER < 1300 || _MSC_VER > 1900 // 1300 == VC++ 7.0, 1900 == VC++ 14.0 +typedef void (__cdecl* init_func_ptr_t)(); +#define BOOST_FILESYSTEM_INITRETSUCCESS_V +#define BOOST_FILESYSTEM_INIT_FUNC void __cdecl +#else +typedef int (__cdecl* init_func_ptr_t)(); +#define BOOST_FILESYSTEM_INITRETSUCCESS_V 0 +#define BOOST_FILESYSTEM_INIT_FUNC int __cdecl +#endif +#else // defined(_MSC_VER) +typedef void (*init_func_ptr_t)(); +#define BOOST_FILESYSTEM_INITRETSUCCESS_V +#define BOOST_FILESYSTEM_INIT_FUNC void +#endif // defined(_MSC_VER) + +#if defined(__has_attribute) +#if __has_attribute(__used__) +#define BOOST_FILESYSTEM_ATTRIBUTE_RETAIN __attribute__ ((__used__)) +#endif +#endif + +#if !defined(BOOST_FILESYSTEM_ATTRIBUTE_RETAIN) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 402 +#define BOOST_FILESYSTEM_ATTRIBUTE_RETAIN __attribute__ ((__used__)) +#endif + +#if !defined(BOOST_FILESYSTEM_ATTRIBUTE_RETAIN) +#define BOOST_FILESYSTEM_NO_ATTRIBUTE_RETAIN +#define BOOST_FILESYSTEM_ATTRIBUTE_RETAIN +#endif + +#endif // BOOST_FILESYSTEM_SRC_PRIVATE_CONFIG_HPP_ diff --git a/libs/filesystem/src/unique_path.cpp b/libs/filesystem/src/unique_path.cpp new file mode 100644 index 0000000..f0bc605 --- /dev/null +++ b/libs/filesystem/src/unique_path.cpp @@ -0,0 +1,331 @@ +// filesystem unique_path.cpp --------------------------------------------------------// + +// Copyright Beman Dawes 2010 +// Copyright Andrey Semashev 2020 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include +#include +#include + +#ifdef BOOST_POSIX_API + +#include +#include +#include +#ifdef BOOST_HAS_UNISTD_H +#include +#endif + +#if !defined(BOOST_FILESYSTEM_DISABLE_ARC4RANDOM) +#if BOOST_OS_BSD_OPEN >= BOOST_VERSION_NUMBER(2, 1, 0) || \ + BOOST_OS_BSD_FREE >= BOOST_VERSION_NUMBER(8, 0, 0) || \ + BOOST_LIB_C_CLOUDABI +#include +#define BOOST_FILESYSTEM_HAS_ARC4RANDOM +#endif +#endif // !defined(BOOST_FILESYSTEM_DISABLE_ARC4RANDOM) + +#if !defined(BOOST_FILESYSTEM_DISABLE_GETRANDOM) +#if (defined(__linux__) || defined(__linux) || defined(linux)) && \ + (!defined(__ANDROID__) || __ANDROID_API__ >= 28) +#include +#if defined(SYS_getrandom) +#define BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL +#endif // defined(SYS_getrandom) +#if defined(__has_include) +#if __has_include() +#define BOOST_FILESYSTEM_HAS_GETRANDOM +#endif +#elif defined(__GLIBC__) +#if __GLIBC_PREREQ(2, 25) +#define BOOST_FILESYSTEM_HAS_GETRANDOM +#endif +#endif // BOOST_FILESYSTEM_HAS_GETRANDOM definition +#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) +#include +#endif +#endif // (defined(__linux__) || defined(__linux) || defined(linux)) && (!defined(__ANDROID__) || __ANDROID_API__ >= 28) +#endif // !defined(BOOST_FILESYSTEM_DISABLE_GETRANDOM) + +#include "posix_tools.hpp" + +#else // BOOST_WINDOWS_API + +// We use auto-linking below to help users of static builds of Boost.Filesystem to link to whatever Windows SDK library we selected. +// The dependency information is currently not exposed in CMake config files generated by Boost.Build (https://github.com/boostorg/boost_install/issues/18), +// which makes it non-trivial for users to discover the libraries they need. This feature is deprecated and may be removed in the future, +// when the situation with CMake config files improves. +// Note that the library build system is the principal source of linking the library, which must work regardless of auto-linking. +#include +#include + +#if defined(BOOST_FILESYSTEM_HAS_BCRYPT) // defined on the command line by the project +#include +#include +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER) +#pragma comment(lib, "bcrypt.lib") +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER) +#else // defined(BOOST_FILESYSTEM_HAS_BCRYPT) +#include +#include +#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER) +#if !defined(_WIN32_WCE) +#pragma comment(lib, "advapi32.lib") +#else +#pragma comment(lib, "coredll.lib") +#endif +#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER) +#endif // defined(BOOST_FILESYSTEM_HAS_BCRYPT) + +#endif // BOOST_POSIX_API + +#include +#include +#include +#include "private_config.hpp" +#include "atomic_tools.hpp" +#include "error_handling.hpp" + +#include // must be the last #include + +#if defined(BOOST_POSIX_API) +// At least Mac OS X 10.6 and older doesn't support O_CLOEXEC +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif +#endif // defined(BOOST_POSIX_API) + +namespace boost { +namespace filesystem { +namespace detail { + +namespace { + +#if defined(BOOST_POSIX_API) && !defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM) + +//! Fills buffer with cryptographically random data obtained from /dev/(u)random +int fill_random_dev_random(void* buf, std::size_t len) +{ + int file = ::open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (file == -1) + { + file = ::open("/dev/random", O_RDONLY | O_CLOEXEC); + if (file == -1) + return errno; + } + + std::size_t bytes_read = 0u; + while (bytes_read < len) + { + ssize_t n = ::read(file, buf, len - bytes_read); + if (BOOST_UNLIKELY(n == -1)) + { + int err = errno; + if (err == EINTR) + continue; + close_fd(file); + return err; + } + bytes_read += n; + buf = static_cast< char* >(buf) + n; + } + + close_fd(file); + return 0; +} + +#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL) + +typedef int fill_random_t(void* buf, std::size_t len); + +//! Pointer to the implementation of fill_random. +fill_random_t* fill_random = &fill_random_dev_random; + +//! Fills buffer with cryptographically random data obtained from getrandom() +int fill_random_getrandom(void* buf, std::size_t len) +{ + std::size_t bytes_read = 0u; + while (bytes_read < len) + { +#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) + ssize_t n = ::getrandom(buf, len - bytes_read, 0u); +#else + ssize_t n = ::syscall(SYS_getrandom, buf, len - bytes_read, 0u); +#endif + if (BOOST_UNLIKELY(n < 0)) + { + const int err = errno; + if (err == EINTR) + continue; + + if (err == ENOSYS && bytes_read == 0u) + { + filesystem::detail::atomic_store_relaxed(fill_random, &fill_random_dev_random); + return fill_random_dev_random(buf, len); + } + + return err; + } + + bytes_read += n; + buf = static_cast< char* >(buf) + n; + } + + return 0; +} + +#endif // defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL) + +#endif // defined(BOOST_POSIX_API) && !defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM) + +void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* ec) +{ +#if defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL) + + int err = filesystem::detail::atomic_load_relaxed(fill_random)(buf, len); + if (BOOST_UNLIKELY(err != 0)) + emit_error(err, ec, "boost::filesystem::unique_path"); + +#elif defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM) + + arc4random_buf(buf, len); + +#else + + int err = fill_random_dev_random(buf, len); + if (BOOST_UNLIKELY(err != 0)) + emit_error(err, ec, "boost::filesystem::unique_path"); + +#endif + +#else // defined(BOOST_POSIX_API) + +#if defined(BOOST_FILESYSTEM_HAS_BCRYPT) + + boost::winapi::BCRYPT_ALG_HANDLE_ handle; + boost::winapi::NTSTATUS_ status = boost::winapi::BCryptOpenAlgorithmProvider(&handle, boost::winapi::BCRYPT_RNG_ALGORITHM_, NULL, 0); + if (BOOST_UNLIKELY(status != 0)) + { + fail: + emit_error(translate_ntstatus(status), ec, "boost::filesystem::unique_path"); + return; + } + + status = boost::winapi::BCryptGenRandom(handle, static_cast< boost::winapi::PUCHAR_ >(buf), static_cast< boost::winapi::ULONG_ >(len), 0); + + boost::winapi::BCryptCloseAlgorithmProvider(handle, 0); + + if (BOOST_UNLIKELY(status != 0)) + goto fail; + +#else // defined(BOOST_FILESYSTEM_HAS_BCRYPT) + + boost::winapi::HCRYPTPROV_ handle; + boost::winapi::DWORD_ err = 0u; + if (BOOST_UNLIKELY(!boost::winapi::CryptAcquireContextW(&handle, NULL, NULL, boost::winapi::PROV_RSA_FULL_, boost::winapi::CRYPT_VERIFYCONTEXT_ | boost::winapi::CRYPT_SILENT_))) + { + err = boost::winapi::GetLastError(); + + fail: + emit_error(err, ec, "boost::filesystem::unique_path"); + return; + } + + boost::winapi::BOOL_ gen_ok = boost::winapi::CryptGenRandom(handle, static_cast< boost::winapi::DWORD_ >(len), static_cast< boost::winapi::BYTE_* >(buf)); + + if (BOOST_UNLIKELY(!gen_ok)) + err = boost::winapi::GetLastError(); + + boost::winapi::CryptReleaseContext(handle, 0); + + if (BOOST_UNLIKELY(!gen_ok)) + goto fail; + +#endif // defined(BOOST_FILESYSTEM_HAS_BCRYPT) + +#endif // defined(BOOST_POSIX_API) +} + +#ifdef BOOST_WINDOWS_API +BOOST_CONSTEXPR_OR_CONST wchar_t hex[] = L"0123456789abcdef"; +BOOST_CONSTEXPR_OR_CONST wchar_t percent = L'%'; +#else +BOOST_CONSTEXPR_OR_CONST char hex[] = "0123456789abcdef"; +BOOST_CONSTEXPR_OR_CONST char percent = '%'; +#endif + +} // unnamed namespace + +#if defined(linux) || defined(__linux) || defined(__linux__) + +//! Initializes fill_random implementation pointer +void init_fill_random_impl(unsigned int major_ver, unsigned int minor_ver, unsigned int patch_ver) +{ +#if defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) && \ + (defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL)) + fill_random_t* fr = &fill_random_dev_random; + + if (major_ver > 3u || (major_ver == 3u && minor_ver >= 17u)) + fr = &fill_random_getrandom; + + filesystem::detail::atomic_store_relaxed(fill_random, fr); +#endif +} + +#endif // defined(linux) || defined(__linux) || defined(__linux__) + +BOOST_FILESYSTEM_DECL +path unique_path(path const& model, system::error_code* ec) +{ + // This function used wstring for fear of misidentifying + // a part of a multibyte character as a percent sign. + // However, double byte encodings only have 80-FF as lead + // bytes and 40-7F as trailing bytes, whereas % is 25. + // So, use string on POSIX and avoid conversions. + + path::string_type s(model.native()); + + char ran[16] = {}; // init to avoid clang static analyzer message + // see ticket #8954 + BOOST_CONSTEXPR_OR_CONST unsigned int max_nibbles = 2u * sizeof(ran); // 4-bits per nibble + + unsigned int nibbles_used = max_nibbles; + for (path::string_type::size_type i = 0, n = s.size(); i < n; ++i) + { + if (s[i] == percent) // digit request + { + if (nibbles_used == max_nibbles) + { + system_crypt_random(ran, sizeof(ran), ec); + if (ec && *ec) + return path(); + nibbles_used = 0; + } + unsigned int c = ran[nibbles_used / 2u]; + c >>= 4u * (nibbles_used++ & 1u); // if odd, shift right 1 nibble + s[i] = hex[c & 0xf]; // convert to hex digit and replace + } + } + + if (ec) + ec->clear(); + + return s; +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include diff --git a/libs/filesystem/src/utf8_codecvt_facet.cpp b/libs/filesystem/src/utf8_codecvt_facet.cpp new file mode 100644 index 0000000..7e5939b --- /dev/null +++ b/libs/filesystem/src/utf8_codecvt_facet.cpp @@ -0,0 +1,29 @@ +// Copyright Vladimir Prus 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include "platform_config.hpp" + +#include + +#include + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { \ + namespace filesystem { \ + namespace detail { + +#define BOOST_UTF8_END_NAMESPACE \ + } \ + } \ + } +#define BOOST_UTF8_DECL BOOST_FILESYSTEM_DECL + +#include + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + +#include diff --git a/libs/filesystem/src/windows_file_codecvt.cpp b/libs/filesystem/src/windows_file_codecvt.cpp new file mode 100644 index 0000000..f86ba51 --- /dev/null +++ b/libs/filesystem/src/windows_file_codecvt.cpp @@ -0,0 +1,72 @@ +// filesystem windows_file_codecvt.cpp -----------------------------------------// + +// Copyright Beman Dawes 2009 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#include "platform_config.hpp" + +#include // for mbstate_t + +#ifdef BOOST_WINDOWS_API + +#include "windows_file_codecvt.hpp" + +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { +namespace detail { + +std::codecvt_base::result windows_file_codecvt::do_in( + std::mbstate_t&, + const char* from, const char* from_end, const char*& from_next, + wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const +{ + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + int count; + if ((count = ::MultiByteToWideChar(codepage, MB_PRECOMPOSED, from, static_cast< int >(from_end - from), to, static_cast< int >(to_end - to))) == 0) + { + return error; // conversion failed + } + + from_next = from_end; + to_next = to + count; + *to_next = L'\0'; + return ok; +} + +std::codecvt_base::result windows_file_codecvt::do_out( + std::mbstate_t&, + const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, + char* to, char* to_end, char*& to_next) const +{ + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + int count; + if ((count = ::WideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, from, static_cast< int >(from_end - from), to, static_cast< int >(to_end - to), 0, 0)) == 0) + { + return error; // conversion failed + } + + from_next = from_end; + to_next = to + count; + *to_next = '\0'; + return ok; +} + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_WINDOWS_API diff --git a/libs/filesystem/src/windows_file_codecvt.hpp b/libs/filesystem/src/windows_file_codecvt.hpp new file mode 100644 index 0000000..917dc21 --- /dev/null +++ b/libs/filesystem/src/windows_file_codecvt.hpp @@ -0,0 +1,72 @@ +// filesystem windows_file_codecvt.hpp -----------------------------------------------// + +// Copyright Beman Dawes 2009 + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// Library home page: http://www.boost.org/libs/filesystem + +#ifndef BOOST_FILESYSTEM_WINDOWS_FILE_CODECVT_HPP +#define BOOST_FILESYSTEM_WINDOWS_FILE_CODECVT_HPP + +#include + +#ifdef BOOST_WINDOWS_API + +#include +#include +#include // std::mbstate_t +#include + +#include // must be the last #include + +namespace boost { +namespace filesystem { +namespace detail { + +//------------------------------------------------------------------------------------// +// // +// class windows_file_codecvt // +// // +// Warning: partial implementation; even do_in and do_out only partially meet the // +// standard library specifications as the "to" buffer must hold the entire result. // +// // +//------------------------------------------------------------------------------------// + +class BOOST_SYMBOL_VISIBLE windows_file_codecvt BOOST_FINAL : + public std::codecvt< wchar_t, char, std::mbstate_t > +{ +public: + explicit windows_file_codecvt(std::size_t refs = 0) : + std::codecvt< wchar_t, char, std::mbstate_t >(refs) + { + } + +protected: + bool do_always_noconv() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return false; } + + // seems safest to assume variable number of characters since we don't + // actually know what codepage is active + int do_encoding() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return 0; } + std::codecvt_base::result do_in(std::mbstate_t& state, const char* from, const char* from_end, const char*& from_next, wchar_t* to, wchar_t* to_end, wchar_t*& to_next) const BOOST_OVERRIDE; + std::codecvt_base::result do_out(std::mbstate_t& state, const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, char* to, char* to_end, char*& to_next) const BOOST_OVERRIDE; + std::codecvt_base::result do_unshift(std::mbstate_t&, char* /*from*/, char* /*to*/, char*& /*next*/) const BOOST_OVERRIDE { return ok; } + int do_length(std::mbstate_t&, const char* /*from*/, const char* /*from_end*/, std::size_t /*max*/) const +#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) + throw() +#endif + BOOST_OVERRIDE + { return 0; } + int do_max_length() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { return 0; } +}; + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_WINDOWS_API + +#endif // BOOST_FILESYSTEM_WINDOWS_FILE_CODECVT_HPP diff --git a/libs/filesystem/src/windows_tools.hpp b/libs/filesystem/src/windows_tools.hpp new file mode 100644 index 0000000..ca62bfb --- /dev/null +++ b/libs/filesystem/src/windows_tools.hpp @@ -0,0 +1,281 @@ +// windows_tools.hpp -----------------------------------------------------------------// + +// Copyright 2001 Dietmar Kuehl +// Copyright 2002-2009, 2014 Beman Dawes +// Copyright 2021-2022 Andrey Semashev + +// Distributed under the Boost Software License, Version 1.0. +// See http://www.boost.org/LICENSE_1_0.txt + +// See library home page at http://www.boost.org/libs/filesystem + +//--------------------------------------------------------------------------------------// + +#ifndef BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_ +#define BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_ + +#include +#include +#include +#include +#include // NTSTATUS_ + +#include + +#include // must be the last #include + +#ifndef IO_REPARSE_TAG_DEDUP +#define IO_REPARSE_TAG_DEDUP (0x80000013L) +#endif + +#ifndef IO_REPARSE_TAG_MOUNT_POINT +#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) +#endif + +#ifndef IO_REPARSE_TAG_SYMLINK +#define IO_REPARSE_TAG_SYMLINK (0xA000000CL) +#endif + +namespace boost { +namespace filesystem { +namespace detail { + +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST wchar_t colon = L':'; +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST wchar_t questionmark = L'?'; + +inline bool is_letter(wchar_t c) +{ + return (c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z'); +} + +inline bool equal_extension(wchar_t const* p, wchar_t const (&x1)[5], wchar_t const (&x2)[5]) +{ + return (p[0] == x1[0] || p[0] == x2[0]) && + (p[1] == x1[1] || p[1] == x2[1]) && + (p[2] == x1[2] || p[2] == x2[2]) && + (p[3] == x1[3] || p[3] == x2[3]) && + p[4] == 0; +} + +inline boost::filesystem::perms make_permissions(boost::filesystem::path const& p, DWORD attr) +{ + boost::filesystem::perms prms = boost::filesystem::owner_read | boost::filesystem::group_read | boost::filesystem::others_read; + if ((attr & FILE_ATTRIBUTE_READONLY) == 0u) + prms |= boost::filesystem::owner_write | boost::filesystem::group_write | boost::filesystem::others_write; + boost::filesystem::path ext = detail::path_algorithms::extension_v4(p); + wchar_t const* q = ext.c_str(); + if (equal_extension(q, L".exe", L".EXE") || equal_extension(q, L".com", L".COM") || equal_extension(q, L".bat", L".BAT") || equal_extension(q, L".cmd", L".CMD")) + prms |= boost::filesystem::owner_exe | boost::filesystem::group_exe | boost::filesystem::others_exe; + return prms; +} + +ULONG get_reparse_point_tag_ioctl(HANDLE h, boost::filesystem::path const& p, boost::system::error_code* ec); + +inline bool is_reparse_point_tag_a_symlink(ULONG reparse_point_tag) +{ + return reparse_point_tag == IO_REPARSE_TAG_SYMLINK + // Issue 9016 asked that NTFS directory junctions be recognized as directories. + // That is equivalent to recognizing them as symlinks, and then the normal symlink + // mechanism will take care of recognizing them as directories. + // + // Directory junctions are very similar to symlinks, but have some performance + // and other advantages over symlinks. They can be created from the command line + // with "mklink /J junction-name target-path". + // + // Note that mounted filesystems also have the same repartse point tag, which makes + // them look like directory symlinks in terms of Boost.Filesystem. read_symlink() + // may return a volume path or NT path for such symlinks. + || reparse_point_tag == IO_REPARSE_TAG_MOUNT_POINT; // aka "directory junction" or "junction" +} + +#if !defined(UNDER_CE) + +//! Platform-specific parameters for directory iterator construction +struct directory_iterator_params +{ + //! Handle of the directory to iterate over. If not \c INVALID_HANDLE_VALUE, the directory path is ignored. + HANDLE use_handle; + /*! + * If \c use_handle is not \c INVALID_HANDLE_VALUE, specifies whether the directory iterator should close the handle upon destruction. + * If \c false, the handle must remain valid for the lifetime of the iterator. + */ + bool close_handle; +}; + +//! IO_STATUS_BLOCK definition from Windows SDK. +struct io_status_block +{ + union + { + boost::winapi::NTSTATUS_ Status; + PVOID Pointer; + }; + ULONG_PTR Information; +}; + +//! UNICODE_STRING definition from Windows SDK +struct unicode_string +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; + +//! OBJECT_ATTRIBUTES definition from Windows SDK +struct object_attributes +{ + ULONG Length; + HANDLE RootDirectory; + unicode_string* ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +}; + +#ifndef OBJ_CASE_INSENSITIVE +#define OBJ_CASE_INSENSITIVE 0x00000040 +#endif +#ifndef OBJ_DONT_REPARSE +#define OBJ_DONT_REPARSE 0x00001000 +#endif + +#ifndef FILE_SUPERSEDE +#define FILE_SUPERSEDE 0x00000000 +#endif +#ifndef FILE_OPEN +#define FILE_OPEN 0x00000001 +#endif +#ifndef FILE_CREATE +#define FILE_CREATE 0x00000002 +#endif +#ifndef FILE_OPEN_IF +#define FILE_OPEN_IF 0x00000003 +#endif +#ifndef FILE_OVERWRITE +#define FILE_OVERWRITE 0x00000004 +#endif +#ifndef FILE_OVERWRITE_IF +#define FILE_OVERWRITE_IF 0x00000005 +#endif + +#ifndef FILE_DIRECTORY_FILE +#define FILE_DIRECTORY_FILE 0x00000001 +#endif +#ifndef FILE_SYNCHRONOUS_IO_NONALERT +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#endif +#ifndef FILE_OPEN_FOR_BACKUP_INTENT +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#endif +#ifndef FILE_OPEN_REPARSE_POINT +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#endif + +//! NtCreateFile signature. Available since Windows 2000 (probably). +typedef boost::winapi::NTSTATUS_ (NTAPI NtCreateFile_t)( + /*out*/ PHANDLE FileHandle, + /*in*/ ACCESS_MASK DesiredAccess, + /*in*/ object_attributes* ObjectAttributes, + /*out*/ io_status_block* IoStatusBlock, + /*in, optional*/ PLARGE_INTEGER AllocationSize, + /*in*/ ULONG FileAttributes, + /*in*/ ULONG ShareAccess, + /*in*/ ULONG CreateDisposition, + /*in*/ ULONG CreateOptions, + /*in, optional*/ PVOID EaBuffer, + /*in*/ ULONG EaLength); + +extern NtCreateFile_t* nt_create_file_api; + +//! PIO_APC_ROUTINE definition from Windows SDK +typedef VOID (NTAPI* pio_apc_routine) (PVOID ApcContext, io_status_block* IoStatusBlock, ULONG Reserved); + +//! FILE_INFORMATION_CLASS enum entries +enum file_information_class +{ + file_directory_information_class = 1 +}; + +//! NtQueryDirectoryFile signature. Available since Windows NT 4.0 (probably). +typedef boost::winapi::NTSTATUS_ (NTAPI NtQueryDirectoryFile_t)( + /*in*/ HANDLE FileHandle, + /*in, optional*/ HANDLE Event, + /*in, optional*/ pio_apc_routine ApcRoutine, + /*in, optional*/ PVOID ApcContext, + /*out*/ io_status_block* IoStatusBlock, + /*out*/ PVOID FileInformation, + /*in*/ ULONG Length, + /*in*/ file_information_class FileInformationClass, + /*in*/ BOOLEAN ReturnSingleEntry, + /*in, optional*/ unicode_string* FileName, + /*in*/ BOOLEAN RestartScan); + +extern NtQueryDirectoryFile_t* nt_query_directory_file_api; + +#endif // !defined(UNDER_CE) + +//! FILE_INFO_BY_HANDLE_CLASS enum entries +enum file_info_by_handle_class +{ + file_basic_info_class = 0, + file_disposition_info_class = 4, + file_attribute_tag_info_class = 9, + file_id_both_directory_info_class = 10, + file_id_both_directory_restart_info_class = 11, + file_full_directory_info_class = 14, + file_full_directory_restart_info_class = 15, + file_id_extd_directory_info_class = 19, + file_id_extd_directory_restart_info_class = 20, + file_disposition_info_ex_class = 21 +}; + +//! FILE_ATTRIBUTE_TAG_INFO definition from Windows SDK +struct file_attribute_tag_info +{ + DWORD FileAttributes; + DWORD ReparseTag; +}; + +//! GetFileInformationByHandleEx signature. Available since Windows Vista. +typedef BOOL (WINAPI GetFileInformationByHandleEx_t)( + /*__in*/ HANDLE hFile, + /*__in*/ file_info_by_handle_class FileInformationClass, // the actual type is FILE_INFO_BY_HANDLE_CLASS enum + /*__out_bcount(dwBufferSize)*/ LPVOID lpFileInformation, + /*__in*/ DWORD dwBufferSize); + +extern GetFileInformationByHandleEx_t* get_file_information_by_handle_ex_api; + +//! HANDLE wrapper that automatically closes the handle +struct handle_wrapper +{ + HANDLE handle; + + handle_wrapper() BOOST_NOEXCEPT : handle(INVALID_HANDLE_VALUE) {} + explicit handle_wrapper(HANDLE h) BOOST_NOEXCEPT : handle(h) {} + ~handle_wrapper() BOOST_NOEXCEPT + { + if (handle != INVALID_HANDLE_VALUE) + ::CloseHandle(handle); + } + BOOST_DELETED_FUNCTION(handle_wrapper(handle_wrapper const&)) + BOOST_DELETED_FUNCTION(handle_wrapper& operator=(handle_wrapper const&)) +}; + +//! Creates a file handle +inline HANDLE create_file_handle(boost::filesystem::path const& p, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile = NULL) +{ + return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +} + +#if !defined(UNDER_CE) +//! Creates a file handle for a file relative to a previously opened base directory. The file path must be relative and in preferred format. +boost::winapi::NTSTATUS_ nt_create_file_handle_at(HANDLE& out, HANDLE basedir_handle, boost::filesystem::path const& p, ULONG FileAttributes, ACCESS_MASK DesiredAccess, ULONG ShareMode, ULONG CreateDisposition, ULONG CreateOptions); +#endif // !defined(UNDER_CE) + +} // namespace detail +} // namespace filesystem +} // namespace boost + +#include + +#endif // BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_ diff --git a/libs/url/build/Jamfile b/libs/url/build/Jamfile new file mode 100644 index 0000000..a42674c --- /dev/null +++ b/libs/url/build/Jamfile @@ -0,0 +1,34 @@ +# +# Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) +# Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/vinniefalco/url +# + +project boost/url + : requirements + $(c11-requires) + BOOST_URL_SOURCE + msvc-14.0:no + gcc-7:"-Wno-maybe-uninitialized" # variant2 + gcc,windows:"-Wno-error=array-bounds" + : common-requirements + shared:BOOST_URL_DYN_LINK=1 + static:BOOST_URL_STATIC_LINK=1 + : source-location ../src + ; + +alias url_sources + : [ glob-tree-ex ../src : *.cpp ] + ; + +explicit url_sources ; + +lib boost_url + : url_sources + ; + +boost-install boost_url ; diff --git a/boost/url/impl/authority_view.ipp b/libs/url/src/authority_view.cpp similarity index 95% rename from boost/url/impl/authority_view.ipp rename to libs/url/src/authority_view.cpp index 4bdfae4..d2f151b 100644 --- a/boost/url/impl/authority_view.ipp +++ b/libs/url/src/authority_view.cpp @@ -10,7 +10,9 @@ #ifndef BOOST_URL_IMPL_AUTHORITY_VIEW_IPP #define BOOST_URL_IMPL_AUTHORITY_VIEW_IPP +#include #include +#include #include #include #include @@ -57,7 +59,7 @@ authority_view() noexcept authority_view:: authority_view( - string_view s) + core::string_view s) : authority_view( parse_authority(s ).value(BOOST_URL_POS)) @@ -180,7 +182,7 @@ pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded na ipv4_address host_ipv4_address() // return ipv4_address or {} ipv6_address host_ipv6_address() // return ipv6_address or {} -string_view host_ipvfuture() // return ipvfuture or {} +core::string_view host_ipvfuture() // return ipvfuture or {} std::string host_name() // return decoded name or "" pct_string_view encoded_host_name() // return encoded host name or "" */ @@ -196,7 +198,7 @@ pct_string_view authority_view:: encoded_host_address() const noexcept { - string_view s = u_.get(id_host); + core::string_view s = u_.get(id_host); std::size_t n; switch(u_.host_type_) { @@ -255,14 +257,14 @@ host_ipv6_address() const noexcept return urls::ipv6_address(b); } -string_view +core::string_view authority_view:: host_ipvfuture() const noexcept { if(u_.host_type_ != urls::host_type::ipvfuture) return {}; - string_view s = u_.get(id_host); + core::string_view s = u_.get(id_host); BOOST_ASSERT(s.size() >= 6); BOOST_ASSERT(s.front() == '['); BOOST_ASSERT(s.back() == ']'); @@ -298,7 +300,7 @@ has_port() const noexcept return true; } -string_view +core::string_view authority_view:: port() const noexcept { @@ -332,9 +334,9 @@ encoded_host_and_port() const noexcept // //------------------------------------------------ -result +system::result parse_authority( - string_view s) noexcept + core::string_view s) noexcept { return grammar::parse(s, authority_rule); } diff --git a/boost/url/impl/decode_view.ipp b/libs/url/src/decode_view.cpp similarity index 93% rename from boost/url/impl/decode_view.ipp rename to libs/url/src/decode_view.cpp index 11f3411..4ae6bb5 100644 --- a/boost/url/impl/decode_view.ipp +++ b/libs/url/src/decode_view.cpp @@ -10,7 +10,9 @@ #ifndef BOOST_URL_IMPL_DECODE_VIEW_IPP #define BOOST_URL_IMPL_DECODE_VIEW_IPP +#include #include +#include #include namespace boost { @@ -66,7 +68,7 @@ operator*() const noexcept -> // unchecked constructor decode_view:: decode_view( - string_view s, + core::string_view s, std::size_t n, encoding_opts opt) noexcept : p_(s.data()) @@ -79,7 +81,7 @@ decode_view( int decode_view:: -compare(string_view other) const noexcept +compare(core::string_view other) const noexcept { return detail::decoded_strcmp(*this, other); } @@ -134,7 +136,7 @@ remove_suffix( size_type n ) bool decode_view:: -starts_with( string_view s ) const noexcept +starts_with( core::string_view s ) const noexcept { if (s.size() > size()) return false; @@ -154,7 +156,7 @@ starts_with( string_view s ) const noexcept bool decode_view:: -ends_with( string_view s ) const noexcept +ends_with( core::string_view s ) const noexcept { if (s.size() > size()) return false; diff --git a/boost/url/detail/impl/any_params_iter.ipp b/libs/url/src/detail/any_params_iter.cpp similarity index 96% rename from boost/url/detail/impl/any_params_iter.ipp rename to libs/url/src/detail/any_params_iter.cpp index d2ecab6..d8d46fe 100644 --- a/boost/url/detail/impl/any_params_iter.ipp +++ b/libs/url/src/detail/any_params_iter.cpp @@ -10,8 +10,10 @@ #ifndef BOOST_URL_DETAIL_IMPL_ANY_PARAMS_ITER_IPP #define BOOST_URL_DETAIL_IMPL_ANY_PARAMS_ITER_IPP +#include #include -#include +#include +#include #include namespace boost { @@ -46,7 +48,7 @@ any_params_iter:: query_iter:: query_iter( - string_view s, + core::string_view s, bool ne) noexcept : any_params_iter( s.empty() && ! ne, s) @@ -68,7 +70,7 @@ rewind() noexcept { auto pos = s0.find_first_of('&'); - if(pos != string_view::npos) + if(pos != core::string_view::npos) n_ = pos; else n_ = s0.size(); @@ -93,7 +95,7 @@ measure( encoding_opts opt; opt.space_as_plus = false; n += encoded_size( - string_view(p_, n_), + core::string_view(p_, n_), query_chars, opt); increment(); @@ -115,7 +117,7 @@ copy( dest += encode_unsafe( dest, end - dest, - string_view(p_, n_), + core::string_view(p_, n_), query_chars, opt); increment(); @@ -132,9 +134,9 @@ increment() noexcept return; } ++p_; - string_view s(p_, s0.end() - p_); + core::string_view s(p_, s0.end() - p_); auto pos = s.find_first_of('&'); - if(pos != string_view::npos) + if(pos != core::string_view::npos) n_ = pos; else n_ = s.size(); diff --git a/boost/url/detail/impl/any_segments_iter.ipp b/libs/url/src/detail/any_segments_iter.cpp similarity index 53% rename from boost/url/detail/impl/any_segments_iter.ipp rename to libs/url/src/detail/any_segments_iter.cpp index ee8595b..9e1956f 100644 --- a/boost/url/detail/impl/any_segments_iter.ipp +++ b/libs/url/src/detail/any_segments_iter.cpp @@ -10,8 +10,10 @@ #ifndef BOOST_URL_DETAIL_IMPL_ANY_SEGMENTS_ITER_IPP #define BOOST_URL_DETAIL_IMPL_ANY_SEGMENTS_ITER_IPP +#include +#include #include -#include +#include #include #include @@ -19,194 +21,6 @@ namespace boost { namespace urls { namespace detail { -//------------------------------------------------ -// -// path_iter -// -//------------------------------------------------ - -path_iter:: -path_iter( - string_view s_) noexcept - : any_segments_iter(s_) -{ - rewind(); -} - -void -path_iter:: -increment() noexcept -{ - pos_ = next_; - if(pos_ == s.size()) - { - pos_ = string_view::npos; - return; - } - // skip '/' - ++pos_; - auto const end = - s.data() + s.size(); - auto const p0 = - s.data() + pos_; - auto p = p0; - while(p != end) - { - if(*p == '/') - { - next_ = p - s.data(); - return; - } - ++p; - } - next_ = s.size(); -} - -void -path_iter:: -rewind() noexcept -{ - pos_ = 0; - auto p0 = s.data(); - auto const end = p0 + s.size(); - if(p0 != end) - { - fast_nseg = 1; - // skip leading '/' - // of absolute-path - if(*p0 == '/') - { - ++p0; - ++pos_; - if (p0 == end) - { - fast_nseg = 0; - pos_ = string_view::npos; - } - } - auto p = p0; - while(p != end) - { - if(*p == '/') - { - ++fast_nseg; - break; - } - ++p; - } - front = string_view( - p0, p - p0); - next_ = p - s.data(); - } - else - { - pos_ = string_view::npos; - front = { p0, 0 }; - fast_nseg = 0; - } -} - -bool -path_iter:: -measure( - std::size_t& n) noexcept -{ - if(pos_ == string_view::npos) - return false; - encoding_opts opt; - opt.space_as_plus = false; - n += encoded_size( - s.substr( - pos_, - next_ - pos_), - encode_colons ? - nocolon_pchars : - pchars, - opt); - increment(); - return true; -} - -void -path_iter:: -copy( - char*& dest, - char const* end) noexcept -{ - BOOST_ASSERT(pos_ != - string_view::npos); - encoding_opts opt; - opt.space_as_plus = false; - dest += encode( - dest, - end - dest, - s.substr( - pos_, - next_ - pos_), - encode_colons ? - nocolon_pchars : - pchars, - opt); - increment(); -} - -//------------------------------------------------ -// -// path_encoded_iter -// -//------------------------------------------------ - -path_encoded_iter:: -path_encoded_iter( - pct_string_view s) noexcept - : path_iter(s) -{ -} - -bool -path_encoded_iter:: -measure( - std::size_t& n) noexcept -{ - if(pos_ == string_view::npos) - return false; - encoding_opts opt; - opt.space_as_plus = false; - n += detail::re_encoded_size_unsafe( - s.substr( - pos_, - next_ - pos_), - encode_colons ? - nocolon_pchars : - pchars, - opt); - increment(); - return true; -} - -void -path_encoded_iter:: -copy( - char*& dest, - char const* end) noexcept -{ - BOOST_ASSERT(pos_ != - string_view::npos); - encoding_opts opt; - opt.space_as_plus = false; - detail::re_encode_unsafe( - dest, - end, - s.substr( - pos_, - next_ - pos_), - encode_colons ? - nocolon_pchars : - pchars, - opt); - increment(); -} - //------------------------------------------------ // // segment_iter @@ -215,7 +29,7 @@ copy( segment_iter:: segment_iter( - string_view s_) noexcept + core::string_view s_) noexcept : any_segments_iter(s_) { front = s; @@ -276,7 +90,7 @@ void segments_iter_base:: measure_impl( std::size_t& n, - string_view s, + core::string_view s, bool encode_colons) noexcept { encoding_opts opt; @@ -294,7 +108,7 @@ segments_iter_base:: copy_impl( char*& dest, char const* end, - string_view s, + core::string_view s, bool encode_colons) noexcept { encoding_opts opt; @@ -378,7 +192,7 @@ void segments_encoded_iter_base:: measure_impl( std::size_t& n, - string_view s, + core::string_view s, bool encode_colons) noexcept { encoding_opts opt; @@ -396,7 +210,7 @@ segments_encoded_iter_base:: copy_impl( char*& dest, char const* end, - string_view s, + core::string_view s, bool encode_colons) noexcept { encoding_opts opt; diff --git a/boost/url/detail/impl/decode.ipp b/libs/url/src/detail/decode.cpp similarity index 95% rename from boost/url/detail/impl/decode.ipp rename to libs/url/src/detail/decode.cpp index 0acd2f1..9f6fae7 100644 --- a/boost/url/detail/impl/decode.ipp +++ b/libs/url/src/detail/decode.cpp @@ -10,8 +10,10 @@ #ifndef BOOST_URL_DETAIL_IMPL_DECODE_IPP #define BOOST_URL_DETAIL_IMPL_DECODE_IPP +#include #include #include +#include #include namespace boost { @@ -33,7 +35,7 @@ decode_one( std::size_t decode_bytes_unsafe( - string_view s) noexcept + core::string_view s) noexcept { auto p = s.begin(); auto const end = s.end(); @@ -58,7 +60,7 @@ std::size_t decode_unsafe( char* const dest0, char const* end, - string_view s, + core::string_view s, encoding_opts opt) noexcept { auto it = s.data(); diff --git a/boost/url/detail/impl/except.ipp b/libs/url/src/detail/except.cpp similarity index 81% rename from boost/url/detail/impl/except.ipp rename to libs/url/src/detail/except.cpp index 89bc088..ed07c7d 100644 --- a/boost/url/detail/impl/except.ipp +++ b/libs/url/src/detail/except.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_DETAIL_IMPL_EXCEPT_IPP #define BOOST_URL_DETAIL_IMPL_EXCEPT_IPP +#include #include #include #include @@ -22,7 +23,7 @@ namespace detail { void throw_system_error( - error_code const& ec, + system::error_code const& ec, source_location const& loc) { throw_exception( @@ -31,7 +32,7 @@ throw_system_error( void throw_errc( - errc::errc_t ev, + boost::system::errc::errc_t ev, source_location const& loc) { throw_system_error(make_error_code(ev), loc); @@ -41,14 +42,14 @@ void throw_invalid_argument( source_location const& loc) { - throw_errc(errc::invalid_argument, loc); + throw_errc(boost::system::errc::invalid_argument, loc); } void throw_length_error( source_location const& loc) { - throw_errc(errc::value_too_large, loc); + throw_errc(boost::system::errc::value_too_large, loc); } } // detail diff --git a/boost/url/detail/impl/format_args.ipp b/libs/url/src/detail/format_args.cpp similarity index 95% rename from boost/url/detail/impl/format_args.ipp rename to libs/url/src/detail/format_args.cpp index 3e7fb14..2b69ce2 100644 --- a/boost/url/detail/impl/format_args.ipp +++ b/libs/url/src/detail/format_args.cpp @@ -10,9 +10,14 @@ #ifndef BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_IPP #define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_IPP +#include +#include #include #include +#include +#include #include +#include #include namespace boost { @@ -20,9 +25,9 @@ namespace urls { namespace detail { std::size_t -get_uvalue( string_view a ) +get_uvalue( core::string_view a ) { - string_view str(a); + core::string_view str(a); auto rv = grammar::parse( str, grammar::unsigned_rule{}); if (rv) @@ -33,12 +38,12 @@ get_uvalue( string_view a ) std::size_t get_uvalue( char a ) { - string_view str(&a, 1); + core::string_view str(&a, 1); return get_uvalue(str); } char const* -formatter:: +formatter:: parse(format_parse_context& ctx) { char const* it = ctx.begin(); @@ -137,9 +142,9 @@ parse(format_parse_context& ctx) } std::size_t -formatter:: +formatter:: measure( - string_view str, + core::string_view str, measure_context& ctx, grammar::lut_chars const& cs) const { @@ -159,8 +164,8 @@ measure( } char* -formatter:: -format(string_view str, format_context& ctx, grammar::lut_chars const& cs) const +formatter:: +format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const { std::size_t w = width; if (width_idx != std::size_t(-1) || @@ -205,7 +210,7 @@ format(string_view str, format_context& ctx, grammar::lut_chars const& cs) const void get_width_from_args( std::size_t arg_idx, - string_view arg_name, + core::string_view arg_name, format_args args, std::size_t& w) { @@ -368,13 +373,14 @@ measure( dn += measure_one(sign, cs); ++n; } - while (v > 0) + do { int d = v % 10; v /= 10; dn += measure_one('0' + static_cast(d), cs); ++n; } + while (v > 0); std::size_t w = width; if (width_idx != std::size_t(-1) || @@ -407,13 +413,14 @@ measure( dn += measure_one(sign, cs); ++n; } - while (v != 0) + do { int d = v % 10; v /= 10; dn += measure_one('0' + static_cast(d), cs); ++n; } + while (v != 0); std::size_t w = width; if (width_idx != std::size_t(-1) || @@ -452,13 +459,14 @@ format( { ++n; } - while (v > 0) + do { if (v >= 10) p *= 10; v /= 10; ++n; } + while (v > 0); static constexpr auto m = std::numeric_limits::digits10; BOOST_ASSERT(n <= m + 1); @@ -554,13 +562,14 @@ grammar::lut_chars const& cs) const { ++n; } - while (v > 0) + do { if (v >= 10) p *= 10; v /= 10; ++n; } + while (v > 0); static constexpr auto m = std::numeric_limits::digits10; BOOST_ASSERT(n <= m + 1); diff --git a/boost/url/detail/impl/normalize.ipp b/libs/url/src/detail/normalize.cpp similarity index 91% rename from boost/url/detail/impl/normalize.ipp rename to libs/url/src/detail/normalize.cpp index b23dcad..341a474 100644 --- a/boost/url/detail/impl/normalize.ipp +++ b/libs/url/src/detail/normalize.cpp @@ -11,9 +11,14 @@ #ifndef BOOST_URL_DETAIL_IMPL_NORMALIZE_IPP #define BOOST_URL_DETAIL_IMPL_NORMALIZE_IPP -#include +#include +#include +#include #include +#include +#include #include +#include #include namespace boost { @@ -22,7 +27,7 @@ namespace detail { void pop_encoded_front( - string_view& s, + core::string_view& s, char& c, std::size_t& n) noexcept { @@ -44,8 +49,8 @@ pop_encoded_front( int compare_encoded( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { std::size_t n0 = 0; std::size_t n1 = 0; @@ -73,7 +78,7 @@ compare_encoded( void digest_encoded( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept { char c = 0; @@ -87,8 +92,8 @@ digest_encoded( int ci_compare_encoded( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { std::size_t n0 = 0; std::size_t n1 = 0; @@ -118,7 +123,7 @@ ci_compare_encoded( void ci_digest_encoded( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept { char c = 0; @@ -133,8 +138,8 @@ ci_digest_encoded( int compare( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { auto rlen = (std::min)(lhs.size(), rhs.size()); for (std::size_t i = 0; i < rlen; ++i) @@ -155,8 +160,8 @@ compare( int ci_compare( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { auto rlen = (std::min)(lhs.size(), rhs.size()); for (std::size_t i = 0; i < rlen; ++i) @@ -177,7 +182,7 @@ ci_compare( void ci_digest( - string_view s, + core::string_view s, fnv_1a& hasher) noexcept { for (char c: s) @@ -189,11 +194,11 @@ ci_digest( std::size_t path_starts_with( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { auto consume_one = []( - string_view::iterator& it, + core::string_view::iterator& it, char &c) { if(*it != '%') @@ -205,7 +210,7 @@ path_starts_with( detail::decode_unsafe( &c, &c + 1, - string_view(it, 3)); + core::string_view(it, 3)); if (c != '/') { it += 3; @@ -237,12 +242,12 @@ path_starts_with( std::size_t path_ends_with( - string_view lhs, - string_view rhs) noexcept + core::string_view lhs, + core::string_view rhs) noexcept { auto consume_last = []( - string_view::iterator& it, - string_view::iterator& end, + core::string_view::iterator& it, + core::string_view::iterator& end, char& c) { if ((end - it) < 3 || @@ -254,7 +259,7 @@ path_ends_with( detail::decode_unsafe( &c, &c + 1, - string_view(std::prev( + core::string_view(std::prev( end, 3), 3)); if (c != '/') { @@ -288,7 +293,7 @@ std::size_t remove_dot_segments( char* dest0, char const* end, - string_view s) noexcept + core::string_view s) noexcept { // 1. The input buffer `s` is initialized with // the now-appended path components and the @@ -325,7 +330,7 @@ remove_dot_segments( // - Rule C: apply "..": remove seg and write "/" // - Rule E: copy complete segment auto append = - [](char*& first, char const* last, string_view in) + [](char*& first, char const* last, core::string_view in) { // append `in` to `dest` BOOST_ASSERT(in.size() <= std::size_t(last - first)); @@ -335,7 +340,7 @@ remove_dot_segments( }; auto dot_starts_with = []( - string_view str, string_view dots, std::size_t& n) + core::string_view str, core::string_view dots, std::size_t& n) { // starts_with for encoded/decoded dots // or decoded otherwise. return how many @@ -372,7 +377,7 @@ remove_dot_segments( }; auto dot_equal = [&dot_starts_with]( - string_view str, string_view dots) + core::string_view str, core::string_view dots) { std::size_t n = 0; dot_starts_with(str, dots, n); @@ -421,7 +426,7 @@ remove_dot_segments( } if (dot_equal(s, "/.")) { - // We can't remove "." from a string_view + // We can't remove "." from a core::string_view // So what we do here is equivalent to // replacing s with '/' as required // in Rule B and executing the next @@ -436,13 +441,13 @@ remove_dot_segments( // Rule C if (dot_starts_with(s, "/../", n)) { - std::size_t p = string_view( + std::size_t p = core::string_view( dest0, dest - dest0).find_last_of('/'); - if (p != string_view::npos) + if (p != core::string_view::npos) { // output has multiple segments // "erase" [p, end] if not "/.." - string_view last_seg(dest0 + p, dest - (dest0 + p)); + core::string_view last_seg(dest0 + p, dest - (dest0 + p)); if (!dot_equal(last_seg, "/..")) dest = dest0 + p; else @@ -464,9 +469,9 @@ remove_dot_segments( } if (dot_equal(s, "/..")) { - std::size_t p = string_view( + std::size_t p = core::string_view( dest0, dest - dest0).find_last_of('/'); - if (p != string_view::npos) + if (p != core::string_view::npos) { // erase [p, end] dest = dest0 + p; @@ -486,7 +491,7 @@ remove_dot_segments( // Rule E std::size_t p = s.find_first_of('/', 1); - if (p != string_view::npos) + if (p != core::string_view::npos) { append(dest, end, s.substr(0, p)); s.remove_prefix(p); @@ -505,7 +510,7 @@ remove_dot_segments( } char -path_pop_back( string_view& s ) +path_pop_back( core::string_view& s ) { if (s.size() < 3 || *std::prev(s.end(), 3) != '%') @@ -529,8 +534,8 @@ path_pop_back( string_view& s ) void pop_last_segment( - string_view& s, - string_view& c, + core::string_view& s, + core::string_view& c, std::size_t& level, bool r) noexcept { @@ -592,8 +597,8 @@ pop_last_segment( // the input buffer. std::size_t p = s.size() > 1 ? s.find_last_of('/', s.size() - 2) - : string_view::npos; - if (p != string_view::npos) + : core::string_view::npos; + if (p != core::string_view::npos) { c = s.substr(p + 1); s.remove_suffix(c.size()); @@ -631,11 +636,11 @@ pop_last_segment( void normalized_path_digest( - string_view s, + core::string_view s, bool remove_unmatched, fnv_1a& hasher) noexcept { - string_view child; + core::string_view child; std::size_t level = 0; do { diff --git a/boost/url/detail/impl/params_iter_impl.ipp b/libs/url/src/detail/params_iter_impl.cpp similarity index 99% rename from boost/url/detail/impl/params_iter_impl.ipp rename to libs/url/src/detail/params_iter_impl.cpp index 1da1929..951a321 100644 --- a/boost/url/detail/impl/params_iter_impl.ipp +++ b/libs/url/src/detail/params_iter_impl.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_DETAIL_IMPL_PARAMS_ITER_IMPL_IPP #define BOOST_URL_DETAIL_IMPL_PARAMS_ITER_IMPL_IPP +#include #include #include diff --git a/boost/url/detail/impl/pattern.ipp b/libs/url/src/detail/pattern.cpp similarity index 96% rename from boost/url/detail/impl/pattern.ipp rename to libs/url/src/detail/pattern.cpp index a872d9a..06bb802 100644 --- a/boost/url/detail/impl/pattern.ipp +++ b/libs/url/src/detail/pattern.cpp @@ -10,9 +10,14 @@ #ifndef BOOST_URL_DETAIL_IMPL_PATTERN_IPP #define BOOST_URL_DETAIL_IMPL_PATTERN_IPP +#include #include #include #include +#include +#include +#include +#include #include #include #include @@ -220,7 +225,7 @@ apply( u.impl_.decoded_[parts::id_port] = pct_string_view(dest, dest1 - dest) ->decoded_size() + 1; - string_view up = {dest - 1, dest1}; + core::string_view up = {dest - 1, dest1}; auto p = grammar::parse(up, detail::port_part_rule).value(); if (p.has_port) u.impl_.port_number_ = p.port_number; @@ -326,7 +331,7 @@ apply( fragment_chars, pctx, fctx); u.impl_.decoded_[parts::id_frag] += make_pct_string_view( - string_view(dest, dest1 - dest)) + core::string_view(dest, dest1 - dest)) ->decoded_size() + 1; } } @@ -354,7 +359,7 @@ struct pct_encoded_fmt_string_rule_t CharSet_ const& cs) noexcept -> pct_encoded_fmt_string_rule_t; - result + system::result parse( char const*& it, char const* end) const noexcept @@ -383,7 +388,7 @@ struct pct_encoded_fmt_string_rule_t rv = literal_rule.parse(it, end); } - return string_view(start, it - start); + return core::string_view(start, it - start); } private: @@ -431,7 +436,7 @@ struct fmt_token_rule_t CharSet_ const& cs) noexcept -> fmt_token_rule_t; - result + system::result parse( char const*& it, char const* end) const noexcept @@ -478,7 +483,7 @@ struct fmt_token_rule_t grammar::error::need_more); } - return string_view(start, it - start); + return core::string_view(start, it - start); } private: @@ -507,8 +512,8 @@ struct userinfo_template_rule_t { struct value_type { - string_view user; - string_view password; + core::string_view user; + core::string_view password; bool has_password = false; }; @@ -517,7 +522,7 @@ struct userinfo_template_rule_t char const*& it, char const* end ) const noexcept -> - result + system::result { static constexpr auto uchars = unreserved_chars + @@ -562,14 +567,14 @@ constexpr userinfo_template_rule_t userinfo_template_rule{}; struct host_template_rule_t { - using value_type = string_view; + using value_type = core::string_view; auto parse( char const*& it, char const* end ) const noexcept -> - result + system::result { if(it == end) { @@ -617,7 +622,7 @@ struct host_template_rule_t // the rule might fail to match the // closing "]" BOOST_ASSERT(rv); - return string_view{it0, it}; + return core::string_view{it0, it}; } }; @@ -627,7 +632,7 @@ struct authority_template_rule_t { using value_type = pattern; - result + system::result parse( char const*& it, char const* end @@ -699,9 +704,9 @@ constexpr authority_template_rule_t authority_template_rule{}; struct scheme_template_rule_t { - using value_type = string_view; + using value_type = core::string_view; - result + system::result parse( char const*& it, char const* end) const noexcept @@ -759,7 +764,7 @@ struct scheme_template_rule_t it = grammar::find_if_not( it, end, scheme_chars); } - return string_view(start, it - start); + return core::string_view(start, it - start); } }; @@ -773,7 +778,7 @@ struct pattern_rule_t { using value_type = pattern; - result + system::result parse( char const*& it, char const* const end @@ -930,9 +935,9 @@ struct pattern_rule_t constexpr pattern_rule_t pattern_rule{}; -result +system::result parse_pattern( - string_view s) + core::string_view s) { return grammar::parse( s, pattern_rule); diff --git a/boost/url/detail/impl/pct_format.ipp b/libs/url/src/detail/pct_format.cpp similarity index 96% rename from boost/url/detail/impl/pct_format.ipp rename to libs/url/src/detail/pct_format.cpp index 7bb1ed7..f4172e6 100644 --- a/boost/url/detail/impl/pct_format.ipp +++ b/libs/url/src/detail/pct_format.cpp @@ -10,7 +10,9 @@ #ifndef BOOST_URL_DETAIL_IMPL_PCT_FORMAT_IPP #define BOOST_URL_DETAIL_IMPL_PCT_FORMAT_IPP +#include #include +#include #include namespace boost { @@ -77,7 +79,7 @@ pct_vmeasure( { ++it1; } - string_view id(id_start, it1); + core::string_view id(id_start, it1); // move to specs start if (it1 != end && @@ -176,7 +178,7 @@ pct_vformat( { ++it1; } - string_view id(id_start, it1); + core::string_view id(id_start, it1); // move to specs part if (it1 != end && diff --git a/boost/url/detail/impl/replacement_field_rule.ipp b/libs/url/src/detail/replacement_field_rule.cpp similarity index 91% rename from boost/url/detail/impl/replacement_field_rule.ipp rename to libs/url/src/detail/replacement_field_rule.cpp index 265a8a6..07ca934 100644 --- a/boost/url/detail/impl/replacement_field_rule.ipp +++ b/libs/url/src/detail/replacement_field_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_DETAIL_IMPL_REPLACEMENT_FIELD_RULE_IPP #define BOOST_URL_DETAIL_IMPL_REPLACEMENT_FIELD_RULE_IPP +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include namespace boost { namespace urls { @@ -29,7 +31,7 @@ replacement_field_rule_t:: parse( char const*& it, char const* const end) const noexcept -> - result + system::result { static constexpr auto replacement_field_rules = grammar::tuple_rule( @@ -54,7 +56,7 @@ parse( BOOST_URL_RETURN_EC( grammar::error::mismatch); } - return string_view(it0, it); + return core::string_view(it0, it); } auto @@ -62,7 +64,7 @@ identifier_rule_t:: parse( char const*& it, char const* const end) const noexcept - -> result + -> system::result { static constexpr auto identifier_rules = grammar::tuple_rule( @@ -80,7 +82,7 @@ parse( BOOST_URL_RETURN_EC( grammar::error::mismatch); } - return string_view(it0, it); + return core::string_view(it0, it); } auto @@ -88,7 +90,7 @@ format_spec_rule_t:: parse( char const*& it, char const* const end) const noexcept - -> result + -> system::result { if (it == end) return {}; @@ -126,7 +128,7 @@ parse( } } - return string_view(start, it); + return core::string_view(start, it); } } // detail diff --git a/boost/url/detail/impl/segments_iter_impl.ipp b/libs/url/src/detail/segments_iter_impl.cpp similarity index 96% rename from boost/url/detail/impl/segments_iter_impl.ipp rename to libs/url/src/detail/segments_iter_impl.cpp index 551c6b2..13cbac2 100644 --- a/boost/url/detail/impl/segments_iter_impl.ipp +++ b/libs/url/src/detail/segments_iter_impl.cpp @@ -11,6 +11,8 @@ #ifndef BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_IPP #define BOOST_URL_DETAIL_IMPL_SEGMENTS_ITER_IMPL_IPP +#include +#include #include #include #include @@ -136,7 +138,7 @@ decrement() noexcept { next = pos; pos = path_prefix(ref.buffer()); - s_ = string_view( + s_ = core::string_view( ref.data() + pos, next - pos); BOOST_ASSERT(! s_.ends_with('/')); diff --git a/boost/url/detail/impl/url_impl.ipp b/libs/url/src/detail/url_impl.cpp similarity index 70% rename from boost/url/detail/impl/url_impl.ipp rename to libs/url/src/detail/url_impl.cpp index 447cc3b..1e7a3d6 100644 --- a/boost/url/detail/impl/url_impl.ipp +++ b/libs/url/src/detail/url_impl.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_DETAIL_IMPL_URL_IMPL_IPP #define BOOST_URL_DETAIL_IMPL_URL_IMPL_IPP +#include +#include #include #include #include @@ -19,6 +21,11 @@ namespace boost { namespace urls { namespace detail { +#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + //------------------------------------------------ // // url_impl @@ -28,7 +35,7 @@ namespace detail { void url_impl:: apply_scheme( - string_view s) noexcept + core::string_view s) noexcept { scheme_ = string_to_scheme(s); set_size(id_scheme, s.size() + 1); @@ -87,7 +94,7 @@ apply_host( void url_impl:: apply_port( - string_view s, + core::string_view s, unsigned short pn) noexcept { // this function is for @@ -156,6 +163,146 @@ apply_frag( decoded_[id_frag] = s.decoded_size(); } +// return length of [first, last) +auto +url_impl:: +len( + int first, + int last) const noexcept -> + std::size_t +{ + BOOST_ASSERT(first <= last); + BOOST_ASSERT(last <= id_end); + return offset(last) - offset(first); +} + +// return length of part +auto +url_impl:: +len(int id) const noexcept -> + std::size_t +{ + return id == id_end + ? zero_ + : ( offset(id + 1) - + offset(id) ); +} + +// return offset of id +auto +url_impl:: +offset(int id) const noexcept -> + std::size_t +{ + return + id == id_scheme + ? zero_ + : offset_[id]; +} + +// return id as string +core::string_view +url_impl:: +get(int id) const noexcept +{ + return { + cs_ + offset(id), len(id) }; +} + +// return [first, last) as string +core::string_view +url_impl:: +get(int first, + int last) const noexcept +{ + return { cs_ + offset(first), + offset(last) - offset(first) }; +} + +// return id as pct-string +pct_string_view +url_impl:: +pct_get( + int id) const noexcept +{ + return make_pct_string_view_unsafe( + cs_ + offset(id), + len(id), + decoded_[id]); +} + +// return [first, last) as pct-string +pct_string_view +url_impl:: +pct_get( + int first, + int last) const noexcept +{ + auto const pos = offset(first); + std::size_t n = 0; + for(auto i = first; i < last;) + n += decoded_[i++]; + return make_pct_string_view_unsafe( + cs_ + pos, + offset(last) - pos, + n); +} + +//------------------------------------------------ + +// change id to size n +void +url_impl:: +set_size( + int id, + std::size_t n) noexcept +{ + auto d = n - len(id); + for(auto i = id + 1; + i <= id_end; ++i) + offset_[i] += d; +} + +// trim id to size n, +// moving excess into id+1 +void +url_impl:: +split( + int id, + std::size_t n) noexcept +{ + BOOST_ASSERT(id < id_end - 1); + //BOOST_ASSERT(n <= len(id)); + offset_[id + 1] = offset(id) + n; +} + +// add n to [first, last] +void +url_impl:: +adjust( + int first, + int last, + std::size_t n) noexcept +{ + for(int i = first; + i <= last; ++i) + offset_[i] += n; +} + +// set [first, last) offset +void +url_impl:: +collapse( + int first, + int last, + std::size_t n) noexcept +{ + for(int i = first + 1; + i < last; ++i) + offset_[i] = n; +} + + //------------------------------------------------ // // path_ref @@ -172,7 +319,7 @@ path_ref( } else { - string_view s = impl.get(id_path); + core::string_view s = impl.get(id_path); data_ = s.data(); size_ = s.size(); nseg_ = impl.nseg_; @@ -182,7 +329,7 @@ path_ref( path_ref:: path_ref( - string_view s, + core::string_view s, std::size_t dn, std::size_t nseg) noexcept : data_(s.data()) @@ -252,7 +399,7 @@ nseg() const noexcept query_ref:: query_ref( - string_view s, + core::string_view s, std::size_t dn, std::size_t nparam) noexcept : data_(s.data()) @@ -272,7 +419,7 @@ query_ref( } else { - string_view s = impl.get(id_query); + core::string_view s = impl.get(id_query); if (!s.empty()) { s.remove_prefix(1); @@ -362,6 +509,10 @@ nparam() const noexcept return nparam_; } +#if defined(__GNUC__) && ! defined(__clang__) && defined(__MINGW32__) +#pragma GCC diagnostic pop +#endif + } // detail } // urls } // boost diff --git a/libs/url/src/encoding_opts.cpp b/libs/url/src/encoding_opts.cpp new file mode 100644 index 0000000..8675f73 --- /dev/null +++ b/libs/url/src/encoding_opts.cpp @@ -0,0 +1,32 @@ +// +// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/url +// + +#ifndef BOOST_URL_IMPL_ENCONDING_OPTS_IPP +#define BOOST_URL_IMPL_ENCONDING_OPTS_IPP + +#include +#include + +namespace boost { +namespace urls { + +encoding_opts:: +encoding_opts( + bool space_as_plus_, + bool lower_case_, + bool disallow_null_) noexcept + : space_as_plus(space_as_plus_) + , lower_case(lower_case_) + , disallow_null(disallow_null_) +{} + +} // urls +} // boost + +#endif diff --git a/boost/url/impl/error.ipp b/libs/url/src/error.cpp similarity index 92% rename from boost/url/impl/error.ipp rename to libs/url/src/error.cpp index 64f9e07..ad15b83 100644 --- a/boost/url/impl/error.ipp +++ b/libs/url/src/error.cpp @@ -10,7 +10,9 @@ #ifndef BOOST_URL_IMPL_ERROR_IPP #define BOOST_URL_IMPL_ERROR_IPP +#include #include +#include namespace boost { namespace urls { @@ -54,7 +56,7 @@ case error::not_a_base: return "not a base"; return ""; } -error_condition +system::error_condition error_cat_type:: default_error_condition( int ev) const noexcept @@ -67,7 +69,7 @@ default_error_condition( case error::bad_pct_hexdig: case error::incomplete_encoding: case error::missing_pct_hexdig: -return grammar::condition::fatal; + return grammar::condition::fatal; } } @@ -81,11 +83,7 @@ return grammar::condition::fatal; # pragma warning( disable : 4592 ) #endif -#if defined(__cpp_constinit) && __cpp_constinit >= 201907L -constinit error_cat_type error_cat; -#else error_cat_type error_cat; -#endif #if defined(_MSC_VER) && _MSC_VER <= 1900 # pragma warning( pop ) diff --git a/boost/url/grammar/impl/ci_string.ipp b/libs/url/src/grammar/ci_string.cpp similarity index 91% rename from boost/url/grammar/impl/ci_string.ipp rename to libs/url/src/grammar/ci_string.cpp index 484d230..e86b2f9 100644 --- a/boost/url/grammar/impl/ci_string.ipp +++ b/libs/url/src/grammar/ci_string.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_GRAMMAR_IMPL_CI_STRING_IPP #define BOOST_URL_GRAMMAR_IMPL_CI_STRING_IPP +#include #include namespace boost { @@ -25,8 +26,8 @@ namespace detail { bool ci_is_equal( - string_view s0, - string_view s1) noexcept + core::string_view s0, + core::string_view s1) noexcept { auto n = s0.size(); auto p1 = s0.data(); @@ -58,8 +59,8 @@ slow: bool ci_is_less( - string_view s0, - string_view s1) noexcept + core::string_view s0, + core::string_view s1) noexcept { auto p1 = s0.data(); auto p2 = s1.data(); @@ -80,8 +81,8 @@ ci_is_less( int ci_compare( - string_view s0, - string_view s1) noexcept + core::string_view s0, + core::string_view s1) noexcept { int bias; std::size_t n; @@ -121,7 +122,7 @@ ci_compare( std::size_t ci_digest( - string_view s) noexcept + core::string_view s) noexcept { // Only 4 and 8 byte sizes are supported static_assert( diff --git a/boost/url/grammar/impl/dec_octet_rule.ipp b/libs/url/src/grammar/dec_octet_rule.cpp similarity index 92% rename from boost/url/grammar/impl/dec_octet_rule.ipp rename to libs/url/src/grammar/dec_octet_rule.cpp index a4ae2d8..2611fdb 100644 --- a/boost/url/grammar/impl/dec_octet_rule.ipp +++ b/libs/url/src/grammar/dec_octet_rule.cpp @@ -10,8 +10,11 @@ #ifndef BOOST_URL_IMPL_GRAMMAR_DEC_OCTET_RULE_IPP #define BOOST_URL_IMPL_GRAMMAR_DEC_OCTET_RULE_IPP -#include +#include #include +#include +#include +#include namespace boost { namespace urls { @@ -23,7 +26,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { if(it == end) { diff --git a/boost/url/grammar/impl/delim_rule.ipp b/libs/url/src/grammar/delim_rule.cpp similarity index 85% rename from boost/url/grammar/impl/delim_rule.ipp rename to libs/url/src/grammar/delim_rule.cpp index 4341a13..ad21b86 100644 --- a/boost/url/grammar/impl/delim_rule.ipp +++ b/libs/url/src/grammar/delim_rule.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_GRAMMAR_IMPL_DELIM_RULE_IPP #define BOOST_URL_GRAMMAR_IMPL_DELIM_RULE_IPP +#include +#include #include namespace boost { @@ -21,7 +23,7 @@ ch_delim_rule:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { if(it == end) { @@ -35,7 +37,7 @@ parse( BOOST_URL_RETURN_EC( error::mismatch); } - return string_view{ + return core::string_view{ it++, 1 }; }; diff --git a/boost/url/grammar/detail/impl/recycled.ipp b/libs/url/src/grammar/detail/recycled.cpp similarity index 94% rename from boost/url/grammar/detail/impl/recycled.ipp rename to libs/url/src/grammar/detail/recycled.cpp index 755d70e..46d7865 100644 --- a/boost/url/grammar/detail/impl/recycled.ipp +++ b/libs/url/src/grammar/detail/recycled.cpp @@ -7,9 +7,8 @@ // Official repository: https://github.com/boostorg/url // -#ifndef BOOST_URL_GRAMMAR_DETAIL_IMPL_RECYCLED_IPP -#define BOOST_URL_GRAMMAR_DETAIL_IMPL_RECYCLED_IPP - +#include +#include #include #include #include @@ -98,5 +97,3 @@ recycled_remove_impl( } // grammar } // urls } // boost - -#endif diff --git a/boost/url/grammar/impl/error.ipp b/libs/url/src/grammar/error.cpp similarity index 78% rename from boost/url/grammar/impl/error.ipp rename to libs/url/src/grammar/error.cpp index c3e4bde..6b591d8 100644 --- a/boost/url/grammar/impl/error.ipp +++ b/libs/url/src/grammar/error.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_GRAMMAR_IMPL_ERROR_IPP #define BOOST_URL_GRAMMAR_IMPL_ERROR_IPP +#include #include namespace boost { @@ -51,7 +52,7 @@ case error::out_of_range: return "out of range"; } } -error_condition +system::error_condition error_cat_type:: default_error_condition( int ev) const noexcept @@ -95,6 +96,23 @@ message( } } +//----------------------------------------------- + +// msvc 14.0 has a bug that warns about inability +// to use constexpr construction here, even though +// there's no constexpr construction +#if defined(_MSC_VER) && _MSC_VER <= 1900 +# pragma warning( push ) +# pragma warning( disable : 4592 ) +#endif + +error_cat_type error_cat; +condition_cat_type condition_cat; + +#if defined(_MSC_VER) && _MSC_VER <= 1900 +# pragma warning( pop ) +#endif + } // detail } // grammar diff --git a/boost/url/grammar/impl/literal_rule.ipp b/libs/url/src/grammar/literal_rule.cpp similarity index 90% rename from boost/url/grammar/impl/literal_rule.ipp rename to libs/url/src/grammar/literal_rule.cpp index fb18927..c5c2a1d 100644 --- a/boost/url/grammar/impl/literal_rule.ipp +++ b/libs/url/src/grammar/literal_rule.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_GRAMMAR_IMPL_LITERAL_RULE_IPP #define BOOST_URL_GRAMMAR_IMPL_LITERAL_RULE_IPP +#include +#include #include #include #include @@ -23,7 +25,7 @@ literal_rule:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { // Can't have a literal // with an empty string! @@ -40,7 +42,7 @@ parse( error::mismatch); } it += n_; - return string_view( + return core::string_view( it - n_, it); } if(n > 0) diff --git a/boost/url/grammar/impl/string_view_base.ipp b/libs/url/src/grammar/string_view_base.cpp similarity index 94% rename from boost/url/grammar/impl/string_view_base.ipp rename to libs/url/src/grammar/string_view_base.cpp index d10f17c..d507d1b 100644 --- a/boost/url/grammar/impl/string_view_base.ipp +++ b/libs/url/src/grammar/string_view_base.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_IMPL_STRING_VIEW_BASE_IPP #define BOOST_URL_IMPL_STRING_VIEW_BASE_IPP +#include #include #include diff --git a/boost/url/impl/ipv4_address.ipp b/libs/url/src/ipv4_address.cpp similarity index 92% rename from boost/url/impl/ipv4_address.ipp rename to libs/url/src/ipv4_address.cpp index b5fab65..4c2adef 100644 --- a/boost/url/impl/ipv4_address.ipp +++ b/libs/url/src/ipv4_address.cpp @@ -10,8 +10,10 @@ #ifndef BOOST_URL_IMPL_IPV4_ADDRESS_IPP #define BOOST_URL_IMPL_IPV4_ADDRESS_IPP +#include #include #include +#include #include #include @@ -38,7 +40,7 @@ ipv4_address( ipv4_address:: ipv4_address( - string_view s) + core::string_view s) : ipv4_address( parse_ipv4_address(s ).value(BOOST_URL_POS)) @@ -66,7 +68,7 @@ to_uint() const noexcept -> return addr_; } -string_view +core::string_view ipv4_address:: to_buffer( char* dest, @@ -75,7 +77,7 @@ to_buffer( if(dest_size < max_str_len) detail::throw_length_error(); auto n = print_impl(dest); - return string_view(dest, n); + return core::string_view(dest, n); } bool @@ -154,8 +156,8 @@ to_string_impl( auto parse_ipv4_address( - string_view s) noexcept -> - result + core::string_view s) noexcept -> + system::result { return grammar::parse( s, ipv4_address_rule); diff --git a/boost/url/impl/ipv6_address.ipp b/libs/url/src/ipv6_address.cpp similarity index 95% rename from boost/url/impl/ipv6_address.ipp rename to libs/url/src/ipv6_address.cpp index 7892ebc..946a9ef 100644 --- a/boost/url/impl/ipv6_address.ipp +++ b/libs/url/src/ipv6_address.cpp @@ -10,7 +10,9 @@ #ifndef BOOST_URL_IMPL_IPV6_ADDRESS_IPP #define BOOST_URL_IMPL_IPV6_ADDRESS_IPP +#include #include +#include #include #include #include @@ -40,14 +42,14 @@ ipv6_address( ipv6_address:: ipv6_address( - string_view s) + core::string_view s) : ipv6_address( parse_ipv6_address(s ).value(BOOST_URL_POS)) { } -string_view +core::string_view ipv6_address:: to_buffer( char* dest, @@ -56,7 +58,7 @@ to_buffer( if(dest_size < max_str_len) detail::throw_length_error(); auto n = print_impl(dest); - return string_view(dest, n); + return core::string_view(dest, n); } bool @@ -239,8 +241,8 @@ to_string_impl( auto parse_ipv6_address( - string_view s) noexcept -> - result + core::string_view s) noexcept -> + system::result { return grammar::parse( s, ipv6_address_rule); diff --git a/boost/url/impl/params_base.ipp b/libs/url/src/params_base.cpp similarity index 73% rename from boost/url/impl/params_base.ipp rename to libs/url/src/params_base.cpp index 3615d2c..3f4f47e 100644 --- a/boost/url/impl/params_base.ipp +++ b/libs/url/src/params_base.cpp @@ -11,12 +11,17 @@ #ifndef BOOST_URL_IMPL_PARAMS_BASE_IPP #define BOOST_URL_IMPL_PARAMS_BASE_IPP +#include +#include #include +#include #include namespace boost { namespace urls { +//------------------------------------------------ + params_base:: iterator:: iterator( @@ -38,7 +43,6 @@ iterator( { } -//------------------------------------------------ auto params_base:: @@ -64,6 +68,77 @@ operator*() const -> // //------------------------------------------------ +params_base:: +params_base() noexcept + // space_as_plus = true + : opt_(true, false, false) +{ +} + +bool +params_base:: +contains( + core::string_view key, + ignore_case_param ic) const noexcept +{ + return find( + begin(),key, ic) != end(); +} + +auto +params_base:: +find( + core::string_view key, + ignore_case_param ic) const noexcept -> + iterator +{ + return iterator( + find_impl( + begin().it_, key, ic), + opt_); +} + +auto +params_base:: +find( + iterator it, + core::string_view key, + ignore_case_param ic) const noexcept -> + iterator +{ + return iterator( + find_impl( + it.it_, key, ic), + opt_); +} + +auto +params_base:: +find_last( + core::string_view key, + ignore_case_param ic) const noexcept -> + iterator +{ + return iterator( + find_last_impl( + end().it_, key, ic), + opt_); +} + +auto +params_base:: +find_last( + iterator it, + core::string_view key, + ignore_case_param ic) const noexcept -> + iterator +{ + return iterator( + find_last_impl( + it.it_, key, ic), + opt_); +} + params_base:: params_base( detail::query_ref const& ref, @@ -115,7 +190,7 @@ end() const noexcept -> std::size_t params_base:: count( - string_view key, + core::string_view key, ignore_case_param ic) const noexcept { std::size_t n = 0; @@ -140,7 +215,7 @@ detail::params_iter_impl params_base:: find_impl( detail::params_iter_impl it, - string_view key, + core::string_view key, ignore_case_param ic) const noexcept { detail::params_iter_impl end_(ref_, 0); @@ -170,7 +245,7 @@ detail::params_iter_impl params_base:: find_last_impl( detail::params_iter_impl it, - string_view key, + core::string_view key, ignore_case_param ic) const noexcept { detail::params_iter_impl begin_(ref_); diff --git a/boost/url/impl/params_encoded_base.ipp b/libs/url/src/params_encoded_base.cpp similarity index 96% rename from boost/url/impl/params_encoded_base.ipp rename to libs/url/src/params_encoded_base.cpp index d8f665f..e5bb060 100644 --- a/boost/url/impl/params_encoded_base.ipp +++ b/libs/url/src/params_encoded_base.cpp @@ -11,7 +11,10 @@ #ifndef BOOST_URL_IMPL_PARAMS_ENCODED_BASE_IPP #define BOOST_URL_IMPL_PARAMS_ENCODED_BASE_IPP +#include +#include #include +#include #include namespace boost { diff --git a/boost/url/impl/params_encoded_ref.ipp b/libs/url/src/params_encoded_ref.cpp similarity index 92% rename from boost/url/impl/params_encoded_ref.ipp rename to libs/url/src/params_encoded_ref.cpp index 225a38e..df5392b 100644 --- a/boost/url/impl/params_encoded_ref.ipp +++ b/libs/url/src/params_encoded_ref.cpp @@ -11,6 +11,8 @@ #ifndef BOOST_URL_IMPL_PARAMS_ENCODED_REF_IPP #define BOOST_URL_IMPL_PARAMS_ENCODED_REF_IPP +#include +#include #include #include #include @@ -217,6 +219,32 @@ set( } } +auto +params_encoded_ref:: +erase( + iterator pos) noexcept -> + iterator +{ + return erase( + pos, + std::next(pos)); +} + +auto +params_encoded_ref:: +erase( + iterator first, + iterator last) noexcept -> + iterator +{ + core::string_view s("", 0); + return u_->edit_params( + first.it_, + last.it_, + detail::query_iter(s)); +} + + //------------------------------------------------ // // (implementation) diff --git a/boost/url/impl/params_encoded_view.ipp b/libs/url/src/params_encoded_view.cpp similarity index 93% rename from boost/url/impl/params_encoded_view.ipp rename to libs/url/src/params_encoded_view.cpp index da3089f..9a6ffb9 100644 --- a/boost/url/impl/params_encoded_view.ipp +++ b/libs/url/src/params_encoded_view.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_PARAMS_ENCODED_VIEW_IPP #define BOOST_URL_IMPL_PARAMS_ENCODED_VIEW_IPP +#include #include #include @@ -26,7 +27,7 @@ params_encoded_view( params_encoded_view:: params_encoded_view( - string_view s) + core::string_view s) : params_encoded_view( parse_query(s).value( BOOST_URL_POS)) diff --git a/boost/url/impl/params_ref.ipp b/libs/url/src/params_ref.cpp similarity index 88% rename from boost/url/impl/params_ref.ipp rename to libs/url/src/params_ref.cpp index 209ff59..43f97a0 100644 --- a/boost/url/impl/params_ref.ipp +++ b/libs/url/src/params_ref.cpp @@ -11,6 +11,8 @@ #ifndef BOOST_URL_IMPL_PARAMS_REF_IPP #define BOOST_URL_IMPL_PARAMS_REF_IPP +#include +#include #include #include #include @@ -91,7 +93,7 @@ insert( std::size_t params_ref:: erase( - string_view key, + core::string_view key, ignore_case_param ic) noexcept { // end() can't be fully cached, @@ -157,7 +159,7 @@ unset( iterator { BOOST_ASSERT(pos.it_.nk > 0); - string_view s; + core::string_view s; return iterator( u_->edit_params( pos.it_, @@ -171,7 +173,7 @@ auto params_ref:: set( iterator pos, - string_view value) -> + core::string_view value) -> iterator { BOOST_ASSERT(pos.it_.nk > 0); @@ -187,8 +189,8 @@ set( auto params_ref:: set( - string_view key, - string_view value, + core::string_view key, + core::string_view value, ignore_case_param ic) -> iterator { @@ -209,6 +211,33 @@ set( } } +auto +params_ref:: +erase( + iterator pos) noexcept -> + iterator +{ + return erase( + pos, + std::next(pos)); +} + +auto +params_ref:: +erase( + iterator first, + iterator last) noexcept -> + iterator +{ + core::string_view s("", 0); + return iterator( + u_->edit_params( + first.it_, + last.it_, + detail::query_iter(s)), + opt_); +} + //------------------------------------------------ // // (implementation) @@ -219,7 +248,7 @@ detail::params_iter_impl params_ref:: find_impl( detail::params_iter_impl it, - string_view key, + core::string_view key, ignore_case_param ic) const noexcept { detail::params_iter_impl end_(u_->impl_, 0); @@ -249,7 +278,7 @@ detail::params_iter_impl params_ref:: find_last_impl( detail::params_iter_impl it, - string_view key, + core::string_view key, ignore_case_param ic) const noexcept { detail::params_iter_impl begin_(u_->impl_); diff --git a/boost/url/impl/params_view.ipp b/libs/url/src/params_view.cpp similarity index 92% rename from boost/url/impl/params_view.ipp rename to libs/url/src/params_view.cpp index 7ee089d..d741e77 100644 --- a/boost/url/impl/params_view.ipp +++ b/libs/url/src/params_view.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_PARAMS_VIEW_IPP #define BOOST_URL_IMPL_PARAMS_VIEW_IPP +#include #include #include @@ -37,7 +38,7 @@ params_view( params_view:: params_view( - string_view s) + core::string_view s) : params_view( parse_query(s).value( BOOST_URL_POS), @@ -47,7 +48,7 @@ params_view( params_view:: params_view( - string_view s, + core::string_view s, encoding_opts opt) : params_view( parse_query(s).value( diff --git a/boost/url/impl/parse.ipp b/libs/url/src/parse.cpp similarity index 80% rename from boost/url/impl/parse.ipp rename to libs/url/src/parse.cpp index 25b5f26..6f364b2 100644 --- a/boost/url/impl/parse.ipp +++ b/libs/url/src/parse.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_PARSE_IPP #define BOOST_URL_IMPL_PARSE_IPP +#include #include #include #include @@ -22,40 +23,40 @@ namespace boost { namespace urls { -result +system::result parse_absolute_uri( - string_view s) + core::string_view s) { return grammar::parse( s, absolute_uri_rule); } -result +system::result parse_origin_form( - string_view s) + core::string_view s) { return grammar::parse( s, origin_form_rule); } -result +system::result parse_relative_ref( - string_view s) + core::string_view s) { return grammar::parse( s, relative_ref_rule); } -result +system::result parse_uri( - string_view s) + core::string_view s) { return grammar::parse( s, uri_rule); } -result +system::result parse_uri_reference( - string_view s) + core::string_view s) { return grammar::parse( s, uri_reference_rule); diff --git a/boost/url/impl/parse_path.ipp b/libs/url/src/parse_path.cpp similarity index 92% rename from boost/url/impl/parse_path.ipp rename to libs/url/src/parse_path.cpp index 2e4be98..0763285 100644 --- a/boost/url/impl/parse_path.ipp +++ b/libs/url/src/parse_path.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_PARSE_PATH_IPP #define BOOST_URL_IMPL_PARSE_PATH_IPP +#include #include #include #include @@ -20,8 +21,8 @@ namespace boost { namespace urls { -result -parse_path(string_view s) noexcept +system::result +parse_path(core::string_view s) noexcept { auto it = s.data(); auto const end = it + s.size(); diff --git a/boost/url/impl/parse_query.ipp b/libs/url/src/parse_query.cpp similarity index 87% rename from boost/url/impl/parse_query.ipp rename to libs/url/src/parse_query.cpp index a140f78..817d0ce 100644 --- a/boost/url/impl/parse_query.ipp +++ b/libs/url/src/parse_query.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_PARSE_QUERY_IPP #define BOOST_URL_IMPL_PARSE_QUERY_IPP +#include #include #include #include @@ -20,8 +21,8 @@ namespace boost { namespace urls { -result -parse_query(string_view s) noexcept +system::result +parse_query(core::string_view s) noexcept { // Handle empty strings differently. // We produce {}, versus empty but @@ -36,7 +37,7 @@ parse_query(string_view s) noexcept return rv.error(); return params_encoded_view( detail::query_ref( - s.data(), s.size(), rv->size())); + s, s.size(), rv->size())); } } // urls diff --git a/boost/url/impl/pct_string_view.ipp b/libs/url/src/pct_string_view.cpp similarity index 92% rename from boost/url/impl/pct_string_view.ipp rename to libs/url/src/pct_string_view.cpp index 739f687..dd37423 100644 --- a/boost/url/impl/pct_string_view.ipp +++ b/libs/url/src/pct_string_view.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_IMPL_PCT_STRING_VIEW_IPP #define BOOST_URL_IMPL_PCT_STRING_VIEW_IPP +#include +#include #include #include #include @@ -34,7 +36,7 @@ decode_impl( pct_string_view:: pct_string_view( - string_view s) + core::string_view s) : pct_string_view( make_pct_string_view(s ).value(BOOST_URL_POS)) @@ -43,9 +45,9 @@ pct_string_view( //------------------------------------------------ -result +system::result make_pct_string_view( - string_view s) noexcept + core::string_view s) noexcept { auto p = s.begin(); auto const end = s.end(); diff --git a/boost/url/rfc/impl/absolute_uri_rule.ipp b/libs/url/src/rfc/absolute_uri_rule.cpp similarity index 96% rename from boost/url/rfc/impl/absolute_uri_rule.ipp rename to libs/url/src/rfc/absolute_uri_rule.cpp index 660f956..dc31164 100644 --- a/boost/url/rfc/impl/absolute_uri_rule.ipp +++ b/libs/url/src/rfc/absolute_uri_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_RFC_IMPL_ABSOLUTE_URI_RULE_IPP #define BOOST_URL_RFC_IMPL_ABSOLUTE_URI_RULE_IPP +#include #include #include #include @@ -29,7 +30,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { detail::url_impl u(detail::url_impl::from::string); u.cs_ = it; diff --git a/boost/url/rfc/impl/authority_rule.ipp b/libs/url/src/rfc/authority_rule.cpp similarity index 94% rename from boost/url/rfc/impl/authority_rule.ipp rename to libs/url/src/rfc/authority_rule.cpp index ee9e977..11ba864 100644 --- a/boost/url/rfc/impl/authority_rule.ipp +++ b/libs/url/src/rfc/authority_rule.cpp @@ -10,8 +10,10 @@ #ifndef BOOST_URL_RFC_IMPL_AUTHORITY_RULE_IPP #define BOOST_URL_RFC_IMPL_AUTHORITY_RULE_IPP +#include #include #include +#include #include #include #include @@ -27,7 +29,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { detail::url_impl u(detail::url_impl::from::authority); u.cs_ = it; diff --git a/boost/url/rfc/detail/impl/h16_rule.ipp b/libs/url/src/rfc/detail/h16_rule.cpp similarity index 94% rename from boost/url/rfc/detail/impl/h16_rule.ipp rename to libs/url/src/rfc/detail/h16_rule.cpp index d1954cf..af2106f 100644 --- a/boost/url/rfc/detail/impl/h16_rule.ipp +++ b/libs/url/src/rfc/detail/h16_rule.cpp @@ -10,9 +10,11 @@ #ifndef BOOST_URL_RFC_DETAIL_IMPL_H16_RULE_HPP #define BOOST_URL_RFC_DETAIL_IMPL_H16_RULE_HPP +#include #include #include #include +#include #include namespace boost { @@ -25,7 +27,7 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { // VFALCO it might be impossible for // this condition to be true (coverage) diff --git a/boost/url/rfc/detail/impl/hier_part_rule.ipp b/libs/url/src/rfc/detail/hier_part_rule.cpp similarity index 97% rename from boost/url/rfc/detail/impl/hier_part_rule.ipp rename to libs/url/src/rfc/detail/hier_part_rule.cpp index 8dd0cba..6a2447f 100644 --- a/boost/url/rfc/detail/impl/hier_part_rule.ipp +++ b/libs/url/src/rfc/detail/hier_part_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_IPP #define BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_IPP +#include #include #include #include @@ -25,7 +26,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { value_type t; if(it == end) diff --git a/boost/url/rfc/detail/impl/host_rule.ipp b/libs/url/src/rfc/detail/host_rule.cpp similarity index 75% rename from boost/url/rfc/detail/impl/host_rule.ipp rename to libs/url/src/rfc/detail/host_rule.cpp index bff5ed5..5502123 100644 --- a/boost/url/rfc/detail/impl/host_rule.ipp +++ b/libs/url/src/rfc/detail/host_rule.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_RFC_DETAIL_IMPL_HOST_RULE_IPP #define BOOST_URL_RFC_DETAIL_IMPL_HOST_RULE_IPP +#include +#include #include #include #include @@ -25,7 +27,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { value_type t; @@ -58,7 +60,7 @@ parse( b.size()); t.host_type = urls::host_type::ipv6; - t.match = string_view( + t.match = core::string_view( it0, it - it0); return t; } @@ -66,16 +68,33 @@ parse( // IPvFuture t.host_type = urls::host_type::ipvfuture; - t.match = string_view( + t.match = core::string_view( it0, it - it0); return t; } + // IPv4address { auto rv = grammar::parse( it, end, ipv4_address_rule); if( rv ) { + auto it02 = it; + auto rv2 = grammar::parse( + it, end, + detail::reg_name_rule); + if (rv2.has_value() && + !rv2->empty()) + { + t.name = core::string_view( + it0, it - it0); + t.host_type = + urls::host_type::name; + t.match = core::string_view( + it0, it - it0); + return t; + } + it = it02; auto const b = rv->to_bytes(); std::memcpy( @@ -84,13 +103,14 @@ parse( b.size()); t.host_type = urls::host_type::ipv4; - t.match = string_view( + t.match = core::string_view( it0, it - it0); return t; } it = it0; // rewind } + // reg-name { auto rv = grammar::parse( @@ -101,7 +121,7 @@ parse( t.name = *rv; t.host_type = urls::host_type::name; - t.match = string_view( + t.match = core::string_view( it0, it - it0); return t; } diff --git a/boost/url/rfc/detail/impl/ip_literal_rule.ipp b/libs/url/src/rfc/detail/ip_literal_rule.cpp similarity index 72% rename from boost/url/rfc/detail/impl/ip_literal_rule.ipp rename to libs/url/src/rfc/detail/ip_literal_rule.cpp index 3bef686..04547d8 100644 --- a/boost/url/rfc/detail/impl/ip_literal_rule.ipp +++ b/libs/url/src/rfc/detail/ip_literal_rule.cpp @@ -1,5 +1,6 @@ // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -10,12 +11,13 @@ #ifndef BOOST_URL_IMPL_IP_LITERAL_RULE_IPP #define BOOST_URL_IMPL_IP_LITERAL_RULE_IPP +#include +#include #include -#include +#include #include #include #include -#include #include namespace boost { @@ -28,7 +30,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { value_type t; @@ -48,6 +50,7 @@ parse( if(*it != 'v') { // IPv6address + auto it0 = it; auto rv = grammar::parse( it, end, grammar::tuple_rule( @@ -55,7 +58,21 @@ parse( grammar::squelch( grammar::delim_rule(']')))); if(! rv) - return rv.error(); + { + // IPv6addrz + it = it0; + auto rv2 = grammar::parse( + it, end, + grammar::tuple_rule( + ipv6_addrz_rule, + grammar::squelch( + grammar::delim_rule(']')))); + if(! rv2) + return rv2.error(); + t.ipv6 = rv2->ipv6; + t.is_ipv6 = true; + return t; + } t.ipv6 = *rv; t.is_ipv6 = true; return t; diff --git a/libs/url/src/rfc/detail/ipv6_addrz_rule.cpp b/libs/url/src/rfc/detail/ipv6_addrz_rule.cpp new file mode 100644 index 0000000..4602058 --- /dev/null +++ b/libs/url/src/rfc/detail/ipv6_addrz_rule.cpp @@ -0,0 +1,74 @@ +// +// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/url +// + +#ifndef BOOST_URL_RFC_DETAIL_IMPL_IPV6_ADDRZ_RULE_IPP +#define BOOST_URL_RFC_DETAIL_IMPL_IPV6_ADDRZ_RULE_IPP + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace urls { +namespace detail { + +auto +ipv6_addrz_rule_t:: +parse( + char const*& it, + char const* const end + ) const noexcept -> + system::result +{ + value_type t; + auto rv1 = grammar::parse( + it, end, ipv6_address_rule); + if (! rv1) + return rv1.error(); + t.ipv6 = *rv1; + + // "%25" + auto it0 = it; + if (end - it < 3 || + *it != '%' || + *(it + 1) != '2' || + *(it + 2) != '5') + { + BOOST_URL_RETURN_EC( + grammar::error::invalid); + } + it += 3; + + // ZoneID = 1*( unreserved / pct-encoded ) + // Parse as many (unreserved / pct-encoded) + // as available + auto rv2 = grammar::parse( + it, end, + pct_encoded_rule(unreserved_chars)); + if(!rv2 || rv2->empty()) + { + it = it0; + BOOST_URL_RETURN_EC( + grammar::error::invalid); + } + else + { + t.zone_id = *rv2; + } + return t; +} + +} // detail +} // urls +} // boost + +#endif diff --git a/boost/url/rfc/detail/impl/ipvfuture_rule.ipp b/libs/url/src/rfc/detail/ipvfuture_rule.cpp similarity index 92% rename from boost/url/rfc/detail/impl/ipvfuture_rule.ipp rename to libs/url/src/rfc/detail/ipvfuture_rule.cpp index 2ed99d2..875ecb9 100644 --- a/boost/url/rfc/detail/impl/ipvfuture_rule.ipp +++ b/libs/url/src/rfc/detail/ipvfuture_rule.cpp @@ -10,11 +10,13 @@ #ifndef BOOST_URL_DETAIL_IMPL_IPVFUTURE_RULE_IPP #define BOOST_URL_DETAIL_IMPL_IPVFUTURE_RULE_IPP +#include #include #include #include #include #include +#include #include #include #include @@ -29,7 +31,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { static constexpr auto minor_chars = @@ -61,7 +63,7 @@ parse( BOOST_URL_RETURN_EC( grammar::error::invalid); } - t.str = string_view( + t.str = core::string_view( it0, it - it0); return t; } diff --git a/boost/url/rfc/detail/impl/port_rule.ipp b/libs/url/src/rfc/detail/port_rule.cpp similarity index 89% rename from boost/url/rfc/detail/impl/port_rule.ipp rename to libs/url/src/rfc/detail/port_rule.cpp index 5d2aaba..552c2ee 100644 --- a/boost/url/rfc/detail/impl/port_rule.ipp +++ b/libs/url/src/rfc/detail/port_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_IMPL_PORT_RULE_IPP #define BOOST_URL_IMPL_PORT_RULE_IPP +#include #include #include #include @@ -26,7 +27,7 @@ port_rule:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { value_type t; auto const start = it; @@ -45,7 +46,7 @@ parse( if (rv) { // number < max uint16_t - t.str = string_view(start, it); + t.str = core::string_view(start, it); t.has_number = true; t.number = *rv; return t; @@ -60,14 +61,14 @@ parse( { ++it; } - t.str = string_view(start, it); + t.str = core::string_view(start, it); t.has_number = true; t.number = 0; return t; } } // no digits - t.str = string_view(start, it); + t.str = core::string_view(start, it); t.has_number = it != end; t.number = 0; return t; @@ -78,7 +79,7 @@ port_part_rule_t:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { value_type t; if( it == end || diff --git a/boost/url/rfc/detail/impl/relative_part_rule.ipp b/libs/url/src/rfc/detail/relative_part_rule.cpp similarity index 97% rename from boost/url/rfc/detail/impl/relative_part_rule.ipp rename to libs/url/src/rfc/detail/relative_part_rule.cpp index e99f865..5231343 100644 --- a/boost/url/rfc/detail/impl/relative_part_rule.ipp +++ b/libs/url/src/rfc/detail/relative_part_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_IPP #define BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_IPP +#include #include #include #include @@ -26,7 +27,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { value_type t; if(it == end) diff --git a/boost/url/rfc/detail/impl/scheme_rule.ipp b/libs/url/src/rfc/detail/scheme_rule.cpp similarity index 87% rename from boost/url/rfc/detail/impl/scheme_rule.ipp rename to libs/url/src/rfc/detail/scheme_rule.cpp index 3088c58..5f17c4f 100644 --- a/boost/url/rfc/detail/impl/scheme_rule.ipp +++ b/libs/url/src/rfc/detail/scheme_rule.cpp @@ -10,10 +10,13 @@ #ifndef BOOST_URL_IMPL_SCHEME_RULE_IPP #define BOOST_URL_IMPL_SCHEME_RULE_IPP +#include #include +#include #include -#include +#include #include +#include namespace boost { namespace urls { @@ -24,7 +27,7 @@ scheme_rule:: parse( char const*& it, char const* end) const noexcept -> - result + system::result { auto const start = it; if(it == end) @@ -49,7 +52,7 @@ parse( it = grammar::find_if_not( it + 1, end, scheme_chars); value_type t; - t.scheme = string_view( + t.scheme = core::string_view( start, it - start); t.scheme_id = string_to_scheme( t.scheme); diff --git a/boost/url/rfc/detail/impl/userinfo_rule.ipp b/libs/url/src/rfc/detail/userinfo_rule.cpp similarity index 87% rename from boost/url/rfc/detail/impl/userinfo_rule.ipp rename to libs/url/src/rfc/detail/userinfo_rule.cpp index b8a8ee4..c204469 100644 --- a/boost/url/rfc/detail/impl/userinfo_rule.ipp +++ b/libs/url/src/rfc/detail/userinfo_rule.cpp @@ -10,9 +10,12 @@ #ifndef BOOST_URL_RFC_DETAIL_IMPL_USERINFO_RULE_IPP #define BOOST_URL_RFC_DETAIL_IMPL_USERINFO_RULE_IPP +#include #include -#include +#include #include +#include +#include #include namespace boost { @@ -25,7 +28,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { static constexpr auto uchars = unreserved_chars + diff --git a/boost/url/rfc/impl/ipv4_address_rule.ipp b/libs/url/src/rfc/ipv4_address_rule.cpp similarity index 94% rename from boost/url/rfc/impl/ipv4_address_rule.ipp rename to libs/url/src/rfc/ipv4_address_rule.cpp index 17f4933..c3630eb 100644 --- a/boost/url/rfc/impl/ipv4_address_rule.ipp +++ b/libs/url/src/rfc/ipv4_address_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_RFC_IMPL_IPV4_ADDRESS_RULE_IPP #define BOOST_URL_RFC_IMPL_IPV4_ADDRESS_RULE_IPP +#include #include #include #include @@ -25,7 +26,7 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { using namespace grammar; auto rv = grammar::parse( diff --git a/boost/url/rfc/impl/ipv6_address_rule.ipp b/libs/url/src/rfc/ipv6_address_rule.cpp similarity index 96% rename from boost/url/rfc/impl/ipv6_address_rule.ipp rename to libs/url/src/rfc/ipv6_address_rule.cpp index c874660..a424655 100644 --- a/boost/url/rfc/impl/ipv6_address_rule.ipp +++ b/libs/url/src/rfc/ipv6_address_rule.cpp @@ -10,10 +10,12 @@ #ifndef BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_IPP #define BOOST_URL_RFC_IMPL_IPV6_ADDRESS_RULE_IPP +#include #include #include #include #include +#include #include #include #include @@ -53,7 +55,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { int n = 8; // words needed int b = -1; // value of n @@ -61,7 +63,7 @@ parse( bool c = false; // need colon auto prev = it; ipv6_address::bytes_type bytes; - result rv; + system::result rv; for(;;) { if(it == end) diff --git a/boost/url/rfc/impl/origin_form_rule.ipp b/libs/url/src/rfc/origin_form_rule.cpp similarity index 93% rename from boost/url/rfc/impl/origin_form_rule.ipp rename to libs/url/src/rfc/origin_form_rule.cpp index 211afcc..c8b9a4c 100644 --- a/boost/url/rfc/impl/origin_form_rule.ipp +++ b/libs/url/src/rfc/origin_form_rule.cpp @@ -10,9 +10,11 @@ #ifndef BOOST_URL_RFC_IMPL_ORIGIN_FORM_RULE_IPP #define BOOST_URL_RFC_IMPL_ORIGIN_FORM_RULE_IPP +#include #include #include #include +#include #include #include #include @@ -26,7 +28,7 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { detail::url_impl u(detail::url_impl::from::string); u.cs_ = it; diff --git a/boost/url/rfc/impl/query_rule.ipp b/libs/url/src/rfc/query_rule.cpp similarity index 92% rename from boost/url/rfc/impl/query_rule.ipp rename to libs/url/src/rfc/query_rule.cpp index 80f368e..2d46736 100644 --- a/boost/url/rfc/impl/query_rule.ipp +++ b/libs/url/src/rfc/query_rule.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_RFC_IMPL_QUERY_RULE_IPP #define BOOST_URL_RFC_IMPL_QUERY_RULE_IPP +#include #include #include #include @@ -24,14 +25,14 @@ parse( char const*& it, char const* end ) const noexcept -> - result + system::result { if(it == end) { // empty string = 0 params return params_encoded_view( detail::query_ref( - string_view(it, 0), 0, 0)); + core::string_view(it, 0), 0, 0)); } auto const it0 = it; std::size_t dn = 0; @@ -74,7 +75,7 @@ parse( std::size_t const n(it - it0); return params_encoded_view( detail::query_ref( - string_view(it0, n), + core::string_view(it0, n), n - dn, nparam)); } diff --git a/boost/url/rfc/impl/relative_ref_rule.ipp b/libs/url/src/rfc/relative_ref_rule.cpp similarity index 94% rename from boost/url/rfc/impl/relative_ref_rule.ipp rename to libs/url/src/rfc/relative_ref_rule.cpp index c343751..414550e 100644 --- a/boost/url/rfc/impl/relative_ref_rule.ipp +++ b/libs/url/src/rfc/relative_ref_rule.cpp @@ -10,9 +10,11 @@ #ifndef BOOST_URL_RFC_IMPL_RELATIVE_REF_RULE_IPP #define BOOST_URL_RFC_IMPL_RELATIVE_REF_RULE_IPP +#include #include #include #include +#include #include #include #include @@ -28,7 +30,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { detail::url_impl u(detail::url_impl::from::string); u.cs_ = it; diff --git a/boost/url/rfc/impl/uri_reference_rule.ipp b/libs/url/src/rfc/uri_reference_rule.cpp similarity index 84% rename from boost/url/rfc/impl/uri_reference_rule.ipp rename to libs/url/src/rfc/uri_reference_rule.cpp index ffd9433..86c6720 100644 --- a/boost/url/rfc/impl/uri_reference_rule.ipp +++ b/libs/url/src/rfc/uri_reference_rule.cpp @@ -10,11 +10,13 @@ #ifndef BOOST_URL_RFC_IMPL_URI_REFERENCE_RULE_IPP #define BOOST_URL_RFC_IMPL_URI_REFERENCE_RULE_IPP +#include #include #include #include #include #include +#include namespace boost { namespace urls { @@ -25,7 +27,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { auto rv = grammar::parse( it, end, @@ -38,9 +40,9 @@ parse( { default: case 0: - return get<0>(*rv); + return boost::variant2::get<0>(*rv); case 1: - return get<1>(*rv); + return boost::variant2::get<1>(*rv); } } diff --git a/boost/url/rfc/impl/uri_rule.ipp b/libs/url/src/rfc/uri_rule.cpp similarity index 94% rename from boost/url/rfc/impl/uri_rule.ipp rename to libs/url/src/rfc/uri_rule.cpp index f1b3632..c348835 100644 --- a/boost/url/rfc/impl/uri_rule.ipp +++ b/libs/url/src/rfc/uri_rule.cpp @@ -10,10 +10,12 @@ #ifndef BOOST_URL_RFC_IMPL_URI_RULE_IPP #define BOOST_URL_RFC_IMPL_URI_RULE_IPP +#include #include #include #include #include +#include #include #include #include @@ -29,7 +31,7 @@ parse( char const*& it, char const* const end ) const noexcept -> - result + system::result { detail::url_impl u(detail::url_impl::from::string); u.cs_ = it; diff --git a/boost/url/impl/scheme.ipp b/libs/url/src/scheme.cpp similarity index 96% rename from boost/url/impl/scheme.ipp rename to libs/url/src/scheme.cpp index eb8d778..1441ced 100644 --- a/boost/url/impl/scheme.ipp +++ b/libs/url/src/scheme.cpp @@ -10,6 +10,7 @@ #ifndef BOOST_URL_IMPL_SCHEME_IPP #define BOOST_URL_IMPL_SCHEME_IPP +#include #include #include @@ -18,7 +19,7 @@ namespace urls { scheme string_to_scheme( - string_view s) noexcept + core::string_view s) noexcept { using grammar::to_lower; switch(s.size()) @@ -89,7 +90,7 @@ string_to_scheme( return scheme::unknown; } -string_view +core::string_view to_string(scheme s) noexcept { switch(s) diff --git a/boost/url/impl/segments_base.ipp b/libs/url/src/segments_base.cpp similarity index 97% rename from boost/url/impl/segments_base.ipp rename to libs/url/src/segments_base.cpp index 9a1ab98..3693f37 100644 --- a/boost/url/impl/segments_base.ipp +++ b/libs/url/src/segments_base.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_BASE_IPP #define BOOST_URL_IMPL_SEGMENTS_BASE_IPP +#include #include #include diff --git a/boost/url/impl/segments_encoded_base.ipp b/libs/url/src/segments_encoded_base.cpp similarity index 98% rename from boost/url/impl/segments_encoded_base.ipp rename to libs/url/src/segments_encoded_base.cpp index 136b9f3..8a6436e 100644 --- a/boost/url/impl/segments_encoded_base.ipp +++ b/libs/url/src/segments_encoded_base.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_ENCODED_BASE_IPP #define BOOST_URL_IMPL_SEGMENTS_ENCODED_BASE_IPP +#include #include #include #include diff --git a/boost/url/impl/segments_encoded_ref.ipp b/libs/url/src/segments_encoded_ref.cpp similarity index 98% rename from boost/url/impl/segments_encoded_ref.ipp rename to libs/url/src/segments_encoded_ref.cpp index 6a99298..be61fd8 100644 --- a/boost/url/impl/segments_encoded_ref.ipp +++ b/libs/url/src/segments_encoded_ref.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_ENCODED_REF_IPP #define BOOST_URL_IMPL_SEGMENTS_ENCODED_REF_IPP +#include #include #include #include @@ -117,7 +118,7 @@ erase( iterator last) noexcept -> iterator { - string_view s; + core::string_view s; return u_->edit_segments( first.it_, last.it_, diff --git a/boost/url/impl/segments_encoded_view.ipp b/libs/url/src/segments_encoded_view.cpp similarity index 93% rename from boost/url/impl/segments_encoded_view.ipp rename to libs/url/src/segments_encoded_view.cpp index 510a35a..ab01d2a 100644 --- a/boost/url/impl/segments_encoded_view.ipp +++ b/libs/url/src/segments_encoded_view.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_ENCODED_VIEW_IPP #define BOOST_URL_IMPL_SEGMENTS_ENCODED_VIEW_IPP +#include #include #include @@ -26,7 +27,7 @@ segments_encoded_view( segments_encoded_view:: segments_encoded_view( - string_view s) + core::string_view s) : segments_encoded_view( parse_path(s).value( BOOST_URL_POS)) diff --git a/boost/url/impl/segments_ref.ipp b/libs/url/src/segments_ref.cpp similarity index 90% rename from boost/url/impl/segments_ref.ipp rename to libs/url/src/segments_ref.cpp index cf20cca..80a0723 100644 --- a/boost/url/impl/segments_ref.ipp +++ b/libs/url/src/segments_ref.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_REF_IPP #define BOOST_URL_IMPL_SEGMENTS_REF_IPP +#include #include #include #include @@ -61,7 +62,7 @@ operator=(segments_view const& other) segments_ref& segments_ref:: operator=(std::initializer_list< - string_view> init) + core::string_view> init) { assign(init.begin(), init.end()); return *this; @@ -76,7 +77,7 @@ operator=(std::initializer_list< void segments_ref:: assign(std::initializer_list< - string_view> init) + core::string_view> init) { assign(init.begin(), init.end()); } @@ -85,7 +86,7 @@ auto segments_ref:: insert( iterator before, - string_view s) -> + core::string_view s) -> iterator { return u_->edit_segments( @@ -99,7 +100,7 @@ segments_ref:: insert( iterator before, std::initializer_list< - string_view> init) -> + core::string_view> init) -> iterator { return insert( @@ -116,7 +117,7 @@ erase( iterator last) noexcept -> iterator { - string_view s; + core::string_view s; return u_->edit_segments( first.it_, last.it_, @@ -128,7 +129,7 @@ auto segments_ref:: replace( iterator pos, - string_view s) -> + core::string_view s) -> iterator { return u_->edit_segments( @@ -142,7 +143,7 @@ segments_ref:: replace( iterator from, iterator to, - string_view s) -> + core::string_view s) -> iterator { return u_->edit_segments( @@ -157,7 +158,7 @@ replace( iterator from, iterator to, std::initializer_list< - string_view> init) -> + core::string_view> init) -> iterator { return replace( diff --git a/boost/url/impl/segments_view.ipp b/libs/url/src/segments_view.cpp similarity index 92% rename from boost/url/impl/segments_view.ipp rename to libs/url/src/segments_view.cpp index a243efd..a28f2ea 100644 --- a/boost/url/impl/segments_view.ipp +++ b/libs/url/src/segments_view.cpp @@ -11,6 +11,7 @@ #ifndef BOOST_URL_IMPL_SEGMENTS_VIEW_IPP #define BOOST_URL_IMPL_SEGMENTS_VIEW_IPP +#include #include #include @@ -26,7 +27,7 @@ segments_view( segments_view:: segments_view( - string_view s) + core::string_view s) : segments_view( parse_path(s).value( BOOST_URL_POS)) diff --git a/boost/url/impl/static_url.ipp b/libs/url/src/static_url.cpp similarity index 92% rename from boost/url/impl/static_url.ipp rename to libs/url/src/static_url.cpp index 578356d..770730a 100644 --- a/boost/url/impl/static_url.ipp +++ b/libs/url/src/static_url.cpp @@ -10,6 +10,8 @@ #ifndef BOOST_URL_IMPL_STATIC_URL_IPP #define BOOST_URL_IMPL_STATIC_URL_IPP +#include +#include #include #include #include @@ -33,7 +35,7 @@ static_url_base:: static_url_base( char* buf, std::size_t cap, - string_view s) + core::string_view s) : static_url_base(buf, cap) { copy(parse_uri_reference(s diff --git a/boost/url/impl/url.ipp b/libs/url/src/url.cpp similarity index 95% rename from boost/url/impl/url.ipp rename to libs/url/src/url.cpp index 3d19b77..8bfd3bd 100644 --- a/boost/url/impl/url.ipp +++ b/libs/url/src/url.cpp @@ -11,7 +11,9 @@ #ifndef BOOST_URL_IMPL_URL_IPP #define BOOST_URL_IMPL_URL_IPP +#include #include +#include #include namespace boost { @@ -35,7 +37,7 @@ url:: url() noexcept = default; url:: -url(string_view s) +url(core::string_view s) : url(parse_uri_reference(s ).value(BOOST_URL_POS)) { @@ -98,8 +100,7 @@ clear_impl() noexcept } else { - BOOST_ASSERT(impl_.cs_ == - detail::empty_c_str_); + BOOST_ASSERT(impl_.cs_[0] == 0); } } diff --git a/boost/url/impl/url_base.ipp b/libs/url/src/url_base.cpp similarity index 85% rename from boost/url/impl/url_base.ipp rename to libs/url/src/url_base.cpp index 6b20fc9..0d33d3a 100644 --- a/boost/url/impl/url_base.ipp +++ b/libs/url/src/url_base.cpp @@ -11,17 +11,23 @@ #ifndef BOOST_URL_IMPL_URL_BASE_IPP #define BOOST_URL_IMPL_URL_BASE_IPP +#include #include +#include #include #include #include #include #include #include +#include #include #include #include +#include +#include #include +#include #include #include #include @@ -59,8 +65,8 @@ url_base:: op_t:: op_t( url_base& impl_, - string_view* s0_, - string_view* s1_) noexcept + core::string_view* s0_, + core::string_view* s1_) noexcept : u(impl_) , s0(s0_) , s1(s1_) @@ -141,7 +147,7 @@ copy(url_view_base const& u) url_base& url_base:: -set_scheme(string_view s) +set_scheme(core::string_view s) { set_scheme_impl( s, string_to_scheme(s)); @@ -344,7 +350,7 @@ remove_authority() url_base& url_base:: set_userinfo( - string_view s) + core::string_view s) { op_t op(*this, &s); encoding_opts opt; @@ -360,7 +366,7 @@ set_userinfo( auto const pos = impl_.get( id_user, id_host ).find_first_of(':'); - if(pos != string_view::npos) + if(pos != core::string_view::npos) { impl_.split(id_user, pos); // find ':' in plain string @@ -387,7 +393,7 @@ set_encoded_userinfo( op_t op(*this, &detail::ref(s)); encoding_opts opt; auto const pos = s.find_first_of(':'); - if(pos != string_view::npos) + if(pos != core::string_view::npos) { // user:pass auto const s0 = s.substr(0, pos); @@ -460,7 +466,7 @@ remove_userinfo() noexcept url_base& url_base:: -set_user(string_view s) +set_user(core::string_view s) { op_t op(*this, &s); encoding_opts opt; @@ -505,7 +511,7 @@ set_encoded_user( url_base& url_base:: -set_password(string_view s) +set_password(core::string_view s) { op_t op(*this, &s); encoding_opts opt; @@ -580,21 +586,21 @@ pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded na ipv4_address host_ipv4_address() // return ipv4_address or {} ipv6_address host_ipv6_address() // return ipv6_address or {} -string_view host_ipvfuture() // return ipvfuture or {} +core::string_view host_ipvfuture() // return ipvfuture or {} std::string host_name() // return decoded name or "" pct_string_view encoded_host_name() // return encoded host name or "" -------------------------------------------------- -set_host( string_view ) // set host part from plain text +set_host( core::string_view ) // set host part from plain text set_encoded_host( pct_string_view ) // set host part from encoded text -set_host_address( string_view ) // set host from ipv4, ipv6, ipvfut, or plain reg-name string +set_host_address( core::string_view ) // set host from ipv4, ipv6, ipvfut, or plain reg-name string set_encoded_host_address( pct_string_view ) // set host from ipv4, ipv6, ipvfut, or encoded reg-name string set_host_ipv4( ipv4_address ) // set ipv4 set_host_ipv6( ipv6_address ) // set ipv6 -set_host_ipvfuture( string_view ) // set ipvfuture -set_host_name( string_view ) // set name from plain +set_host_ipvfuture( core::string_view ) // set ipvfuture +set_host_name( core::string_view ) // set name from plain set_encoded_host_name( pct_string_view ) // set name from encoded */ @@ -602,7 +608,7 @@ set_encoded_host_name( pct_string_view ) // set name from encoded url_base& url_base:: set_host( - string_view s) + core::string_view s) { if( s.size() > 2 && s.front() == '[' && @@ -709,7 +715,7 @@ set_encoded_host( url_base& url_base:: set_host_address( - string_view s) + core::string_view s) { { // IPv6-address @@ -844,7 +850,7 @@ set_host_ipv6( url_base& url_base:: set_host_ipvfuture( - string_view s) + core::string_view s) { op_t op(*this, &s); // validate @@ -865,7 +871,7 @@ set_host_ipvfuture( url_base& url_base:: set_host_name( - string_view s) + core::string_view s) { bool is_ipv4 = false; if(s.size() >= 7) // "0.0.0.0" @@ -953,7 +959,7 @@ set_port_number( url_base& url_base:: set_port( - string_view s) + core::string_view s) { op_t op(*this, &s); auto t = grammar::parse(s, @@ -1045,7 +1051,7 @@ set_path_absolute( auto p = encoded_path(); auto pos = p.find_first_of(":/", 1); - if (pos != string_view::npos && + if (pos != core::string_view::npos && p[pos] == ':') { // prepend with . @@ -1086,15 +1092,117 @@ set_path_absolute( url_base& url_base:: set_path( - string_view s) + core::string_view s) { - edit_segments( - detail::segments_iter_impl( - detail::path_ref(impl_)), - detail::segments_iter_impl( - detail::path_ref(impl_), 0), - detail::path_iter(s), - s.starts_with('/')); + op_t op(*this, &s); + encoding_opts opt; + +//------------------------------------------------ +// +// Calculate encoded size +// +// - "/"s are not encoded +// - "%2F"s are not encoded +// +// - reserved path chars are re-encoded +// - colons in first segment might need to be re-encoded +// - the path might need to receive a prefix + auto const n = encoded_size( + s, detail::path_chars, opt); + std::size_t n_reencode_colons = 0; + core::string_view first_seg; + if (!has_scheme() && + !has_authority() && + !s.starts_with('/')) + { + // the first segment with unencoded colons would look + // like the scheme + first_seg = detail::to_sv(s); + std::size_t p = s.find('/'); + if (p != core::string_view::npos) + first_seg = s.substr(0, p); + n_reencode_colons = std::count( + first_seg.begin(), first_seg.end(), ':'); + } + // the authority can only be followed by an empty or relative path + // if we have an authority and the path is a non-empty relative path, we + // add the "/" prefix to make it valid. + bool make_absolute = + has_authority() && + !s.starts_with('/') && + !s.empty(); + // a path starting with "//" might look like the authority. + // we add a "/." prefix to prevent that + bool add_dot_segment = + !make_absolute && + s.starts_with("//"); + +//------------------------------------------------ +// +// Re-encode data +// + auto dest = set_path_impl( + n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); + impl_.decoded_[id_path] = 0; + if (!dest) + { + impl_.nseg_ = 0; + return *this; + } + if (make_absolute) + { + *dest++ = '/'; + impl_.decoded_[id_path] += 1; + } + else if (add_dot_segment) + { + *dest++ = '/'; + *dest++ = '.'; + impl_.decoded_[id_path] += 2; + } + dest += encode_unsafe( + dest, + impl_.get(id_query).data() - dest, + first_seg, + detail::segment_chars - ':', + opt); + dest += encode_unsafe( + dest, + impl_.get(id_query).data() - dest, + s.substr(first_seg.size()), + detail::path_chars, + opt); + impl_.decoded_[id_path] += s.size(); + BOOST_ASSERT(!dest || dest == impl_.get(id_query).data()); + BOOST_ASSERT( + impl_.decoded_[id_path] == + s.size() + make_absolute + 2 * add_dot_segment); + +//------------------------------------------------ +// +// Update path parameters +// + // get the encoded_path with the replacements we applied + if (s == "/") + { + // "/" maps to sequence {} + impl_.nseg_ = 0; + } + else if (!s.empty()) + { + if (s.starts_with("/./")) + s = s.substr(2); + // count segments as number of '/'s + 1 + impl_.nseg_ = std::count( + s.begin() + 1, s.end(), '/') + 1; + } + else + { + // an empty relative path maps to sequence {} + impl_.nseg_ = 0; + } + + check_invariants(); return *this; } @@ -1103,13 +1211,114 @@ url_base:: set_encoded_path( pct_string_view s) { - edit_segments( - detail::segments_iter_impl( - detail::path_ref(impl_)), - detail::segments_iter_impl( - detail::path_ref(impl_), 0), - detail::path_encoded_iter(s), - s.starts_with('/')); + op_t op(*this, &detail::ref(s)); + encoding_opts opt; + +//------------------------------------------------ +// +// Calculate re-encoded output size +// +// - reserved path chars are re-encoded +// - colons in first segment might need to be re-encoded +// - the path might need to receive a prefix + auto const n = detail::re_encoded_size_unsafe( + s, detail::path_chars, opt); + std::size_t n_reencode_colons = 0; + core::string_view first_seg; + if (!has_scheme() && + !has_authority() && + !s.starts_with('/')) + { + // the first segment with unencoded colons would look + // like the scheme + first_seg = detail::to_sv(s); + std::size_t p = s.find('/'); + if (p != core::string_view::npos) + first_seg = s.substr(0, p); + n_reencode_colons = std::count( + first_seg.begin(), first_seg.end(), ':'); + } + // the authority can only be followed by an empty or relative path + // if we have an authority and the path is a non-empty relative path, we + // add the "/" prefix to make it valid. + bool make_absolute = + has_authority() && + !s.starts_with('/') && + !s.empty(); + // a path starting with "//" might look like the authority + // we add a "/." prefix to prevent that + bool add_dot_segment = + !make_absolute && + !has_authority() && + s.starts_with("//"); + +//------------------------------------------------ +// +// Re-encode data +// + auto dest = set_path_impl( + n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); + impl_.decoded_[id_path] = 0; + if (!dest) + { + impl_.nseg_ = 0; + return *this; + } + if (make_absolute) + { + *dest++ = '/'; + impl_.decoded_[id_path] += 1; + } + else if (add_dot_segment) + { + *dest++ = '/'; + *dest++ = '.'; + impl_.decoded_[id_path] += 2; + } + impl_.decoded_[id_path] += + detail::re_encode_unsafe( + dest, + impl_.get(id_query).data(), + first_seg, + detail::segment_chars - ':', + opt); + impl_.decoded_[id_path] += + detail::re_encode_unsafe( + dest, + impl_.get(id_query).data(), + s.substr(first_seg.size()), + detail::path_chars, + opt); + BOOST_ASSERT(dest == impl_.get(id_query).data()); + BOOST_ASSERT( + impl_.decoded_[id_path] == + s.decoded_size() + make_absolute + 2 * add_dot_segment); + +//------------------------------------------------ +// +// Update path parameters +// + // get the encoded_path with the replacements we applied + if (s == "/") + { + // "/" maps to sequence {} + impl_.nseg_ = 0; + } + else if (!s.empty()) + { + if (s.starts_with("/./")) + s = s.substr(2); + // count segments as number of '/'s + 1 + impl_.nseg_ = std::count( + s.begin() + 1, s.end(), '/') + 1; + } + else + { + // an empty relative path maps to sequence {} + impl_.nseg_ = 0; + } + + check_invariants(); return *this; } @@ -1136,7 +1345,7 @@ encoded_segments() noexcept url_base& url_base:: set_query( - string_view s) + core::string_view s) { edit_params( detail::params_iter_impl(impl_), @@ -1271,7 +1480,7 @@ remove_fragment() noexcept url_base& url_base:: -set_fragment(string_view s) +set_fragment(core::string_view s) { op_t op(*this, &s); encoding_opts opt; @@ -1326,7 +1535,7 @@ set_encoded_fragment( // //------------------------------------------------ -result +system::result url_base:: resolve( url_view_base const& ref) @@ -1350,7 +1559,8 @@ resolve( // https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.2 // - if(ref.has_scheme()) + if( ref.has_scheme() && + ref.scheme() != scheme()) { reserve_impl(ref.size(), op); copy(ref); @@ -1534,14 +1744,14 @@ url_base:: normalize_path() { op_t op(*this); - normalize_octets_impl(id_path, detail::path_chars, op); - string_view p = impl_.get(id_path); + normalize_octets_impl(id_path, detail::segment_chars, op); + core::string_view p = impl_.get(id_path); char* p_dest = s_ + impl_.offset(id_path); char* p_end = s_ + impl_.offset(id_path + 1); auto pn = p.size(); auto skip_dot = 0; bool encode_colons = false; - string_view first_seg; + core::string_view first_seg; //------------------------------------------------ // @@ -1563,7 +1773,8 @@ normalize_path() skip_dot = 0; } else if ( - !has_scheme()) + !has_scheme() && + !has_authority()) { if (p.starts_with("./")) { @@ -1585,7 +1796,7 @@ normalize_path() while (first_seg.starts_with("./")) first_seg = first_seg.substr(2); auto i = first_seg.find('/'); - if (i != string_view::npos) + if (i != core::string_view::npos) first_seg = first_seg.substr(0, i); encode_colons = first_seg.contains(':'); } @@ -1597,7 +1808,7 @@ normalize_path() // in the first segment first_seg = p; auto i = first_seg.find('/'); - if (i != string_view::npos) + if (i != core::string_view::npos) first_seg = p.substr(0, i); encode_colons = first_seg.contains(':'); } @@ -1622,7 +1833,7 @@ normalize_path() auto begin = s_ + impl_.offset(id_path); auto it = begin; auto end = begin + pn; - while (string_view(it, 2) == "./") + while (core::string_view(it, 2) == "./") it += 2; while (*it != '/' && it != end) @@ -1863,7 +2074,7 @@ shrink_impl( void url_base:: set_scheme_impl( - string_view s, + core::string_view s, urls::scheme id) { op_t op(*this, &s); @@ -1932,12 +2143,22 @@ set_user_impl( return dest + 2; } // add authority + bool const make_absolute = + !is_path_absolute() && + !impl_.get(id_path).empty(); auto dest = resize_impl( - id_user, 2 + n + 1, op); + id_user, 2 + n + 1 + make_absolute, op); impl_.split(id_user, 2 + n); dest[0] = '/'; dest[1] = '/'; dest[2 + n] = '@'; + if (make_absolute) + { + impl_.split(id_pass, 1); + impl_.split(id_host, 0); + impl_.split(id_port, 0); + dest[3 + n] = '/'; + } check_invariants(); return dest + 2; } @@ -1960,15 +2181,25 @@ set_password_impl( return dest + 1; } // add authority + bool const make_absolute = + !is_path_absolute() && + !impl_.get(id_path).empty(); auto const dest = resize_impl( id_user, id_host, - 2 + 1 + n + 1, op); + 2 + 1 + n + 1 + make_absolute, op); impl_.split(id_user, 2); dest[0] = '/'; dest[1] = '/'; dest[2] = ':'; dest[2 + n + 1] = '@'; + if (make_absolute) + { + impl_.split(id_pass, 2 + n); + impl_.split(id_host, 0); + impl_.split(id_port, 0); + dest[4 + n] = '/'; + } check_invariants(); return dest + 3; } @@ -1981,12 +2212,22 @@ set_userinfo_impl( { // "//" {dest} "@" check_invariants(); + bool const make_absolute = + !is_path_absolute() && + !impl_.get(id_path).empty(); auto dest = resize_impl( - id_user, id_host, n + 3, op); + id_user, id_host, n + 3 + make_absolute, op); impl_.split(id_user, n + 2); dest[0] = '/'; dest[1] = '/'; dest[n + 2] = '@'; + if (make_absolute) + { + impl_.split(id_pass, 1); + impl_.split(id_host, 0); + impl_.split(id_port, 0); + dest[3 + n] = '/'; + } check_invariants(); return dest + 2; } @@ -2001,10 +2242,22 @@ set_host_impl( if(impl_.len(id_user) == 0) { // add authority + bool make_absolute = + !is_path_absolute() && + impl_.len(id_path) != 0; + auto pn = impl_.len(id_path); auto dest = resize_impl( - id_user, n + 2, op); + id_user, n + 2 + make_absolute, op); impl_.split(id_user, 2); impl_.split(id_pass, 0); + impl_.split(id_host, n); + impl_.split(id_port, 0); + impl_.split(id_path, pn + make_absolute); + if (make_absolute) + { + dest[n + 2] = '/'; + ++impl_.decoded_[id_path]; + } dest[0] = '/'; dest[1] = '/'; check_invariants(); @@ -2033,23 +2286,45 @@ set_port_impl( check_invariants(); return dest + 1; } + bool make_absolute = + !is_path_absolute() && + impl_.len(id_path) != 0; auto dest = resize_impl( - id_user, 3 + n, op); + id_user, 3 + n + make_absolute, op); impl_.split(id_user, 2); impl_.split(id_pass, 0); impl_.split(id_host, 0); dest[0] = '/'; dest[1] = '/'; dest[2] = ':'; + if (make_absolute) + { + impl_.split(id_port, n + 1); + dest[n + 3] = '/'; + ++impl_.decoded_[id_path]; + } check_invariants(); return dest + 3; } +char* +url_base:: +set_path_impl( + std::size_t n, + op_t& op) +{ + check_invariants(); + auto const dest = resize_impl( + id_path, n, op); + return dest; +} + + //------------------------------------------------ // return the first segment of the path. // this is needed for some algorithms. -string_view +core::string_view url_base:: first_segment() const noexcept { @@ -2062,13 +2337,13 @@ first_segment() const noexcept auto const end = impl_.cs_ + impl_.offset(id_query); if(impl_.nseg_ == 1) - return string_view( + return core::string_view( p0, end - p0); auto p = p0; while(*p != '/') ++p; BOOST_ASSERT(p < end); - return string_view(p0, p - p0); + return core::string_view(p0, p - p0); } detail::segments_iter_impl @@ -2286,7 +2561,7 @@ edit_segments( // calc decoded size of old range auto const dn0 = detail::decode_bytes_unsafe( - string_view( + core::string_view( impl_.cs_ + impl_.offset(id_path) + pos0, @@ -2377,7 +2652,7 @@ edit_segments( // calc decoded size of new range, auto const dn = detail::decode_bytes_unsafe( - string_view(dest0, dest - dest0)); + core::string_view(dest0, dest - dest0)); impl_.decoded_[id_path] += dn - dn0; return detail::segments_iter_impl( @@ -2419,7 +2694,7 @@ edit_params( // minus one if '?' or '&' prefixed auto const dn0 = detail::decode_bytes_unsafe( - string_view( + core::string_view( impl_.cs_ + pos0, pos1 - pos0)) - ( impl_.len(id_query) > 0); @@ -2520,7 +2795,7 @@ edit_params( // minus one if '?' or '&' prefixed auto const dn = detail::decode_bytes_unsafe( - string_view(dest0, dest - dest0)) - ( + core::string_view(dest0, dest - dest0)) - ( impl_.len(id_query) > 0); impl_.decoded_[id_query] += (dn - dn0); diff --git a/boost/url/impl/url_view.ipp b/libs/url/src/url_view.cpp similarity index 93% rename from boost/url/impl/url_view.ipp rename to libs/url/src/url_view.cpp index 973664a..20ce147 100644 --- a/boost/url/impl/url_view.ipp +++ b/libs/url/src/url_view.cpp @@ -11,7 +11,9 @@ #ifndef BOOST_URL_IMPL_URL_VIEW_IPP #define BOOST_URL_IMPL_URL_VIEW_IPP +#include #include +#include #include namespace boost { @@ -34,7 +36,7 @@ url_view:: url_view() noexcept = default; url_view:: -url_view(string_view s) +url_view(core::string_view s) : url_view(parse_uri_reference(s ).value(BOOST_URL_POS)) { diff --git a/boost/url/impl/url_view_base.ipp b/libs/url/src/url_view_base.cpp similarity index 94% rename from boost/url/impl/url_view_base.ipp rename to libs/url/src/url_view_base.cpp index 25cdf41..1a2d3ae 100644 --- a/boost/url/impl/url_view_base.ipp +++ b/libs/url/src/url_view_base.cpp @@ -11,8 +11,11 @@ #ifndef BOOST_URL_IMPL_URL_VIEW_BASE_IPP #define BOOST_URL_IMPL_URL_VIEW_BASE_IPP +#include #include +#include #include +#include #include namespace boost { @@ -114,7 +117,7 @@ has_scheme() const noexcept return true; } -string_view +core::string_view url_view_base:: scheme() const noexcept { @@ -310,7 +313,7 @@ pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded na ipv4_address host_ipv4_address() // return ipv4_address or {} ipv6_address host_ipv6_address() // return ipv6_address or {} -string_view host_ipvfuture() // return ipvfuture or {} +core::string_view host_ipvfuture() // return ipvfuture or {} std::string host_name() // return decoded name or "" pct_string_view encoded_host_name() // return encoded host name or "" */ @@ -326,7 +329,7 @@ pct_string_view url_view_base:: encoded_host_address() const noexcept { - string_view s = pi_->get(id_host); + core::string_view s = pi_->get(id_host); std::size_t n; switch(pi_->host_type_) { @@ -387,14 +390,14 @@ host_ipv6_address() const noexcept return urls::ipv6_address(b); } -string_view +core::string_view url_view_base:: host_ipvfuture() const noexcept { if(pi_->host_type_ != urls::host_type::ipvfuture) return {}; - string_view s = pi_->get(id_host); + core::string_view s = pi_->get(id_host); BOOST_ASSERT(s.size() >= 6); BOOST_ASSERT(s.front() == '['); BOOST_ASSERT(s.back() == ']'); @@ -409,13 +412,31 @@ encoded_host_name() const noexcept if(pi_->host_type_ != urls::host_type::name) return {}; - string_view s = pi_->get(id_host); + core::string_view s = pi_->get(id_host); return make_pct_string_view_unsafe( s.data(), s.size(), pi_->decoded_[id_host]); } +pct_string_view +url_view_base:: +encoded_zone_id() const noexcept +{ + if(pi_->host_type_ != + urls::host_type::ipv6) + return {}; + core::string_view s = pi_->get(id_host); + BOOST_ASSERT(s.front() == '['); + BOOST_ASSERT(s.back() == ']'); + s = s.substr(1, s.size() - 2); + auto pos = s.find("%25"); + if (pos == core::string_view::npos) + return {}; + s.remove_prefix(pos + 3); + return *make_pct_string_view(s); +} + //------------------------------------------------ bool @@ -430,7 +451,7 @@ has_port() const noexcept return true; } -string_view +core::string_view url_view_base:: port() const noexcept {