argv_traverser.ipp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // (C) Copyright Gennadiy Rozental 2005-2008.
  2. // Use, modification, and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. // File : $RCSfile$
  8. //
  9. // Version : $Revision: 49312 $
  10. //
  11. // Description : implements facility to hide input traversing details
  12. // ***************************************************************************
  13. #ifndef BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER
  14. #define BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER
  15. // Boost.Runtime.Parameter
  16. #include <boost/test/utils/runtime/trace.hpp>
  17. #include <boost/test/utils/runtime/cla/argv_traverser.hpp>
  18. // STL
  19. #include <memory>
  20. #include <cstring>
  21. #ifdef BOOST_NO_STDC_NAMESPACE
  22. namespace std { using ::memcpy; }
  23. #endif
  24. namespace boost {
  25. namespace BOOST_RT_PARAM_NAMESPACE {
  26. namespace cla {
  27. // ************************************************************************** //
  28. // ************** runtime::cla::argv_traverser ************** //
  29. // ************************************************************************** //
  30. BOOST_RT_PARAM_INLINE
  31. argv_traverser::argv_traverser()
  32. : p_ignore_mismatch( false ), p_separator( BOOST_RT_PARAM_LITERAL( ' ' ) )
  33. {
  34. }
  35. //____________________________________________________________________________//
  36. BOOST_RT_PARAM_INLINE void
  37. argv_traverser::init( int argc, char_type** argv )
  38. {
  39. for( int index = 1; index < argc; ++index ) {
  40. m_buffer += argv[index];
  41. if( index != argc-1 )
  42. m_buffer += BOOST_RT_PARAM_LITERAL( ' ' );
  43. }
  44. m_remainder.reset( new char_type[m_buffer.size()+1] );
  45. m_remainder_size = 0;
  46. m_work_buffer = m_buffer;
  47. m_commited_end = m_work_buffer.begin();
  48. BOOST_RT_PARAM_TRACE( "Input buffer: " << m_buffer );
  49. next_token();
  50. }
  51. //____________________________________________________________________________//
  52. BOOST_RT_PARAM_INLINE void
  53. argv_traverser::remainder( int& argc, char_type** argv )
  54. {
  55. argc = 1;
  56. std::size_t pos = 0;
  57. while(pos < m_remainder_size ) {
  58. argv[argc++] = m_remainder.get() + pos;
  59. pos = std::find( m_remainder.get() + pos, m_remainder.get() + m_remainder_size,
  60. BOOST_RT_PARAM_LITERAL( ' ' ) ) - m_remainder.get();
  61. m_remainder[pos++] = BOOST_RT_PARAM_LITERAL( '\0' );
  62. }
  63. }
  64. //____________________________________________________________________________//
  65. BOOST_RT_PARAM_INLINE cstring
  66. argv_traverser::token() const
  67. {
  68. return m_token;
  69. }
  70. //____________________________________________________________________________//
  71. BOOST_RT_PARAM_INLINE void
  72. argv_traverser::next_token()
  73. {
  74. if( m_work_buffer.is_empty() )
  75. return;
  76. m_work_buffer.trim_left( m_token.size() ); // skip remainder of current token
  77. if( m_work_buffer.size() != m_buffer.size() ) // !! is there a better way to identify first token
  78. m_work_buffer.trim_left( 1 ); // skip separator if not first token;
  79. m_token.assign( m_work_buffer.begin(),
  80. std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
  81. }
  82. //____________________________________________________________________________//
  83. BOOST_RT_PARAM_INLINE cstring
  84. argv_traverser::input() const
  85. {
  86. return m_work_buffer;
  87. }
  88. //____________________________________________________________________________//
  89. BOOST_RT_PARAM_INLINE void
  90. argv_traverser::trim( std::size_t size )
  91. {
  92. m_work_buffer.trim_left( size );
  93. if( size <= m_token.size() )
  94. m_token.trim_left( size );
  95. else {
  96. m_token.assign( m_work_buffer.begin(),
  97. std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
  98. }
  99. }
  100. //____________________________________________________________________________//
  101. BOOST_RT_PARAM_INLINE bool
  102. argv_traverser::match_front( cstring str )
  103. {
  104. return m_work_buffer.size() < str.size() ? false : m_work_buffer.substr( 0, str.size() ) == str;
  105. }
  106. //____________________________________________________________________________//
  107. BOOST_RT_PARAM_INLINE bool
  108. argv_traverser::match_front( char_type c )
  109. {
  110. return first_char( m_work_buffer ) == c;
  111. }
  112. //____________________________________________________________________________//
  113. BOOST_RT_PARAM_INLINE bool
  114. argv_traverser::eoi() const
  115. {
  116. return m_work_buffer.is_empty();
  117. }
  118. //____________________________________________________________________________//
  119. BOOST_RT_PARAM_INLINE void
  120. argv_traverser::commit()
  121. {
  122. m_commited_end = m_work_buffer.begin();
  123. }
  124. //____________________________________________________________________________//
  125. BOOST_RT_PARAM_INLINE void
  126. argv_traverser::rollback()
  127. {
  128. m_work_buffer.assign( m_commited_end, m_work_buffer.end() );
  129. m_token.assign( m_work_buffer.begin(),
  130. std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
  131. }
  132. //____________________________________________________________________________//
  133. BOOST_RT_PARAM_INLINE std::size_t
  134. argv_traverser::input_pos() const
  135. {
  136. return m_work_buffer.begin() - m_commited_end;
  137. }
  138. //____________________________________________________________________________//
  139. BOOST_RT_PARAM_INLINE bool
  140. argv_traverser::handle_mismatch()
  141. {
  142. if( !p_ignore_mismatch )
  143. return false;
  144. std::memcpy( m_remainder.get() + m_remainder_size, token().begin(), token().size() );
  145. m_remainder_size += token().size();
  146. m_remainder[m_remainder_size++] = p_separator;
  147. next_token();
  148. commit();
  149. return true;
  150. }
  151. //____________________________________________________________________________//
  152. } // namespace cla
  153. } // namespace BOOST_RT_PARAM_NAMESPACE
  154. } // namespace boost
  155. #endif // BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER