// (C) Copyright Gennadiy Rozental 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/test for the library home page. // Boost.Runtime.Param #include #include namespace rt = boost::runtime; namespace cla = boost::runtime::cla; // STL #include #include //_____________________________________________________________________// struct Point : std::pair { bool parse( rt::cstring& in ) { in.trim_left(); if( first_char( in ) != '(' ) return false; in.trim_left( 1 ); rt::cstring::size_type pos = in.find( ")" ); if( pos == rt::cstring::npos ) return false; rt::cstring ss( in.begin(), pos ); pos = ss.find( "," ); if( pos == rt::cstring::npos ) return false; rt::cstring f( ss.begin(), pos ); rt::cstring s( ss.begin()+pos+1, ss.end() ); f.trim(); s.trim(); try { first = boost::lexical_cast( f ); second = boost::lexical_cast( s ); } catch( boost::bad_lexical_cast const& ) { return false; } in.trim_left( ss.end()+1 ); return true; } }; std::ostream& operator<<( std::ostream& ostr, Point const& p ) { ostr << '(' << p.first << ',' << p.second << ')'; return ostr; } struct Segment : std::pair { bool parse( rt::cstring& in ) { in.trim_left(); if( first_char( in ) != '[' ) return false; in.trim_left( 1 ); if( !first.parse( in ) ) return false; in.trim_left(); if( first_char( in ) != ',' ) return false; in.trim_left( 1 ); if( !second.parse( in ) ) return false; in.trim_left(); if( first_char( in ) != ']' ) return false; in.trim_left( 1 ); return true; } }; std::ostream& operator<<( std::ostream& ostr, Segment const& p ) { ostr << '[' << p.first << ',' << p.second << ']'; return ostr; } struct Circle : std::pair { bool parse( rt::cstring& in ) { in.trim_left(); if( first_char( in ) != '[' ) return false; in.trim_left( 1 ); if( !first.parse( in ) ) return false; in.trim_left(); if( first_char( in ) != ',' ) return false; in.trim_left( 1 ); rt::cstring::size_type pos = in.find( "]" ); if( pos == rt::cstring::npos ) return false; rt::cstring ss( in.begin(), pos ); ss.trim(); try { second = boost::lexical_cast( ss ); } catch( boost::bad_lexical_cast const& ) { return false; } in.trim_left( pos+1 ); return true; } }; std::ostream& operator<<( std::ostream& ostr, Circle const& p ) { ostr << '[' << p.first << ',' << p.second << ']'; return ostr; } //_____________________________________________________________________// template class ShapeIdPolicy : public cla::identification_policy { rt::cstring m_name; rt::cstring m_usage_str; public: explicit ShapeIdPolicy( rt::cstring name ) : cla::identification_policy( boost::rtti::type_id >() ) , m_name( name ) {} virtual bool responds_to( rt::cstring name ) const { return m_name == name; } virtual bool conflict_with( cla::identification_policy const& ) const { return false; } virtual rt::cstring id_2_report() const { return m_name; } virtual void usage_info( rt::format_stream& fs ) const { fs << m_name; } virtual bool matching( cla::parameter const& p, cla::argv_traverser& tr, bool primary ) const { T s; rt::cstring in = tr.input(); return s.parse( in ); } }; //_____________________________________________________________________// template class ShapeArgumentFactory : public cla::argument_factory { rt::cstring m_usage_str; public: explicit ShapeArgumentFactory( rt::cstring usage ) : m_usage_str( usage ) {} // Argument factory interface virtual rt::argument_ptr produce_using( cla::parameter& p, cla::argv_traverser& tr ) { T s; rt::cstring in = tr.input(); s.parse( in ); tr.trim( in.begin() - tr.input().begin() ); if( !p.actual_argument() ) { rt::argument_ptr res; rt::typed_argument >* new_arg = new rt::typed_argument >( p ); new_arg->p_value.value.push_back( s ); res.reset( new_arg ); return res; } else { std::list& arg_values = rt::arg_value >( *p.actual_argument() ); arg_values.push_back( s ); return p.actual_argument(); } } virtual rt::argument_ptr produce_using( cla::parameter& p, cla::parser const& ) { return rt::argument_ptr(); } virtual void argument_usage_info( rt::format_stream& fs ) { fs << m_usage_str; } }; //_____________________________________________________________________// struct SegmentParam : cla::parameter { SegmentParam() : cla::parameter( m_id_policy, m_arg_factory ) , m_id_policy( "segment" ) , m_arg_factory( ":((P1x,P1y), (P2x,P2y)) ... ((P1x,P1y), (P2x,P2y))" ) {} ShapeIdPolicy m_id_policy; ShapeArgumentFactory m_arg_factory; }; inline boost::shared_ptr segment_param() { return boost::shared_ptr( new SegmentParam ); } //_____________________________________________________________________// struct CircleParam : cla::parameter { CircleParam() : cla::parameter( m_id_policy, m_arg_factory ) , m_id_policy( "circle" ) , m_arg_factory( ":((P1x,P1y), R) ... ((P1x,P1y), R)" ) {} ShapeIdPolicy m_id_policy; ShapeArgumentFactory m_arg_factory; }; inline boost::shared_ptr circle_param() { return boost::shared_ptr( new CircleParam ); } //_____________________________________________________________________// int main() { char* argv[] = { "basic", "[(1,", "1)", ",", "(7,", "-1", ")]", "[(", "1,1)", ",7", "]", "[(3,", "1", ")", ",", "2]", "[", "(2,7", "),", "(5", ",1", ")]" }; int argc = sizeof(argv)/sizeof(char*); try { cla::parser P; P << circle_param() - cla::optional << segment_param() - cla::optional; P.parse( argc, argv ); boost::optional > segments; boost::optional > circles; P.get( "segment", segments ); if( segments ) { std::cout << "segments : "; std::copy( segments->begin(), segments->end(), std::ostream_iterator( std::cout, "; " ) ); std::cout << std::endl; } P.get( "circle", circles ); if( circles ) { std::cout << "circles : "; std::copy( circles->begin(), circles->end(), std::ostream_iterator( std::cout, "; " ) ); std::cout << std::endl; } } catch( rt::logic_error const& ex ) { std::cout << "Logic error: " << ex.msg() << std::endl; return -1; } return 0; } // EOF