replace_storage.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Boost string_algo library replace_storage.hpp header file ---------------------------//
  2. // Copyright Pavol Droba 2002-2003.
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org/ for updates, documentation, and revision history.
  8. #ifndef BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
  9. #define BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
  10. #include <boost/algorithm/string/config.hpp>
  11. #include <algorithm>
  12. #include <boost/mpl/bool.hpp>
  13. #include <boost/algorithm/string/sequence_traits.hpp>
  14. #include <boost/algorithm/string/detail/sequence.hpp>
  15. namespace boost {
  16. namespace algorithm {
  17. namespace detail {
  18. // storage handling routines -----------------------------------------------//
  19. template< typename StorageT, typename OutputIteratorT >
  20. inline OutputIteratorT move_from_storage(
  21. StorageT& Storage,
  22. OutputIteratorT DestBegin,
  23. OutputIteratorT DestEnd )
  24. {
  25. OutputIteratorT OutputIt=DestBegin;
  26. while( !Storage.empty() && OutputIt!=DestEnd )
  27. {
  28. *OutputIt=Storage.front();
  29. Storage.pop_front();
  30. ++OutputIt;
  31. }
  32. return OutputIt;
  33. }
  34. template< typename StorageT, typename WhatT >
  35. inline void copy_to_storage(
  36. StorageT& Storage,
  37. const WhatT& What )
  38. {
  39. Storage.insert( Storage.end(), ::boost::begin(What), ::boost::end(What) );
  40. }
  41. // process segment routine -----------------------------------------------//
  42. template< bool HasStableIterators >
  43. struct process_segment_helper
  44. {
  45. // Optimized version of process_segment for generic sequence
  46. template<
  47. typename StorageT,
  48. typename InputT,
  49. typename ForwardIteratorT >
  50. ForwardIteratorT operator()(
  51. StorageT& Storage,
  52. InputT& /*Input*/,
  53. ForwardIteratorT InsertIt,
  54. ForwardIteratorT SegmentBegin,
  55. ForwardIteratorT SegmentEnd )
  56. {
  57. // Copy data from the storage until the beginning of the segment
  58. ForwardIteratorT It=::boost::algorithm::detail::move_from_storage( Storage, InsertIt, SegmentBegin );
  59. // 3 cases are possible :
  60. // a) Storage is empty, It==SegmentBegin
  61. // b) Storage is empty, It!=SegmentBegin
  62. // c) Storage is not empty
  63. if( Storage.empty() )
  64. {
  65. if( It==SegmentBegin )
  66. {
  67. // Case a) everything is grand, just return end of segment
  68. return SegmentEnd;
  69. }
  70. else
  71. {
  72. // Case b) move the segment backwards
  73. return std::copy( SegmentBegin, SegmentEnd, It );
  74. }
  75. }
  76. else
  77. {
  78. // Case c) -> shift the segment to the left and keep the overlap in the storage
  79. while( It!=SegmentEnd )
  80. {
  81. // Store value into storage
  82. Storage.push_back( *It );
  83. // Get the top from the storage and put it here
  84. *It=Storage.front();
  85. Storage.pop_front();
  86. // Advance
  87. ++It;
  88. }
  89. return It;
  90. }
  91. }
  92. };
  93. template<>
  94. struct process_segment_helper< true >
  95. {
  96. // Optimized version of process_segment for list-like sequence
  97. template<
  98. typename StorageT,
  99. typename InputT,
  100. typename ForwardIteratorT >
  101. ForwardIteratorT operator()(
  102. StorageT& Storage,
  103. InputT& Input,
  104. ForwardIteratorT InsertIt,
  105. ForwardIteratorT SegmentBegin,
  106. ForwardIteratorT SegmentEnd )
  107. {
  108. // Call replace to do the job
  109. ::boost::algorithm::detail::replace( Input, InsertIt, SegmentBegin, Storage );
  110. // Empty the storage
  111. Storage.clear();
  112. // Iterators were not changed, simply return the end of segment
  113. return SegmentEnd;
  114. }
  115. };
  116. // Process one segment in the replace_all algorithm
  117. template<
  118. typename StorageT,
  119. typename InputT,
  120. typename ForwardIteratorT >
  121. inline ForwardIteratorT process_segment(
  122. StorageT& Storage,
  123. InputT& Input,
  124. ForwardIteratorT InsertIt,
  125. ForwardIteratorT SegmentBegin,
  126. ForwardIteratorT SegmentEnd )
  127. {
  128. return
  129. process_segment_helper<
  130. has_stable_iterators<InputT>::value>()(
  131. Storage, Input, InsertIt, SegmentBegin, SegmentEnd );
  132. }
  133. } // namespace detail
  134. } // namespace algorithm
  135. } // namespace boost
  136. #endif // BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP