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 6// See http://www.boost.org/libs/test for the library home page. 7// 8// File : $RCSfile$ 9// 10// Version : $Revision: 49312 $ 11// 12// Description : implements facility to hide input traversing details 13// *************************************************************************** 14 15#ifndef BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER 16#define BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER 17 18// Boost.Runtime.Parameter 19#include <boost/test/utils/runtime/trace.hpp> 20 21#include <boost/test/utils/runtime/cla/argv_traverser.hpp> 22 23// STL 24#include <memory> 25#include <cstring> 26 27#ifdef BOOST_NO_STDC_NAMESPACE 28namespace std { using ::memcpy; } 29#endif 30 31namespace boost { 32 33namespace BOOST_RT_PARAM_NAMESPACE { 34 35namespace cla { 36 37// ************************************************************************** // 38// ************** runtime::cla::argv_traverser ************** // 39// ************************************************************************** // 40 41BOOST_RT_PARAM_INLINE 42argv_traverser::argv_traverser() 43: p_ignore_mismatch( false ), p_separator( BOOST_RT_PARAM_LITERAL( ' ' ) ) 44{ 45} 46 47//____________________________________________________________________________// 48 49BOOST_RT_PARAM_INLINE void 50argv_traverser::init( int argc, char_type** argv ) 51{ 52 for( int index = 1; index < argc; ++index ) { 53 m_buffer += argv[index]; 54 if( index != argc-1 ) 55 m_buffer += BOOST_RT_PARAM_LITERAL( ' ' ); 56 } 57 58 m_remainder.reset( new char_type[m_buffer.size()+1] ); 59 m_remainder_size = 0; 60 m_work_buffer = m_buffer; 61 m_commited_end = m_work_buffer.begin(); 62 63 BOOST_RT_PARAM_TRACE( "Input buffer: " << m_buffer ); 64 65 next_token(); 66} 67 68//____________________________________________________________________________// 69 70BOOST_RT_PARAM_INLINE void 71argv_traverser::remainder( int& argc, char_type** argv ) 72{ 73 argc = 1; 74 std::size_t pos = 0; 75 while(pos < m_remainder_size ) { 76 argv[argc++] = m_remainder.get() + pos; 77 78 pos = std::find( m_remainder.get() + pos, m_remainder.get() + m_remainder_size, 79 BOOST_RT_PARAM_LITERAL( ' ' ) ) - m_remainder.get(); 80 m_remainder[pos++] = BOOST_RT_PARAM_LITERAL( '\0' ); 81 } 82} 83 84//____________________________________________________________________________// 85 86BOOST_RT_PARAM_INLINE cstring 87argv_traverser::token() const 88{ 89 return m_token; 90} 91 92//____________________________________________________________________________// 93 94BOOST_RT_PARAM_INLINE void 95argv_traverser::next_token() 96{ 97 if( m_work_buffer.is_empty() ) 98 return; 99 100 m_work_buffer.trim_left( m_token.size() ); // skip remainder of current token 101 102 if( m_work_buffer.size() != m_buffer.size() ) // !! is there a better way to identify first token 103 m_work_buffer.trim_left( 1 ); // skip separator if not first token; 104 105 m_token.assign( m_work_buffer.begin(), 106 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); 107} 108 109//____________________________________________________________________________// 110 111BOOST_RT_PARAM_INLINE cstring 112argv_traverser::input() const 113{ 114 return m_work_buffer; 115} 116 117//____________________________________________________________________________// 118 119BOOST_RT_PARAM_INLINE void 120argv_traverser::trim( std::size_t size ) 121{ 122 m_work_buffer.trim_left( size ); 123 124 if( size <= m_token.size() ) 125 m_token.trim_left( size ); 126 else { 127 m_token.assign( m_work_buffer.begin(), 128 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); 129 } 130} 131 132//____________________________________________________________________________// 133 134BOOST_RT_PARAM_INLINE bool 135argv_traverser::match_front( cstring str ) 136{ 137 return m_work_buffer.size() < str.size() ? false : m_work_buffer.substr( 0, str.size() ) == str; 138} 139 140//____________________________________________________________________________// 141 142BOOST_RT_PARAM_INLINE bool 143argv_traverser::match_front( char_type c ) 144{ 145 return first_char( m_work_buffer ) == c; 146} 147 148//____________________________________________________________________________// 149 150BOOST_RT_PARAM_INLINE bool 151argv_traverser::eoi() const 152{ 153 return m_work_buffer.is_empty(); 154} 155 156//____________________________________________________________________________// 157 158BOOST_RT_PARAM_INLINE void 159argv_traverser::commit() 160{ 161 m_commited_end = m_work_buffer.begin(); 162} 163 164//____________________________________________________________________________// 165 166BOOST_RT_PARAM_INLINE void 167argv_traverser::rollback() 168{ 169 m_work_buffer.assign( m_commited_end, m_work_buffer.end() ); 170 m_token.assign( m_work_buffer.begin(), 171 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) ); 172 173} 174 175//____________________________________________________________________________// 176 177BOOST_RT_PARAM_INLINE std::size_t 178argv_traverser::input_pos() const 179{ 180 return m_work_buffer.begin() - m_commited_end; 181} 182 183//____________________________________________________________________________// 184 185BOOST_RT_PARAM_INLINE bool 186argv_traverser::handle_mismatch() 187{ 188 if( !p_ignore_mismatch ) 189 return false; 190 191 std::memcpy( m_remainder.get() + m_remainder_size, token().begin(), token().size() ); 192 m_remainder_size += token().size(); 193 m_remainder[m_remainder_size++] = p_separator; 194 195 next_token(); 196 commit(); 197 198 return true; 199} 200 201//____________________________________________________________________________// 202 203} // namespace cla 204 205} // namespace BOOST_RT_PARAM_NAMESPACE 206 207} // namespace boost 208 209#endif // BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER 210