used boost::iterator_adaptor

pull/40/head
Matchman Green 2012-05-11 00:06:05 +08:00
parent 155f4dae77
commit 204e0db62e
5 changed files with 58 additions and 69 deletions

View File

@ -7,6 +7,7 @@ find_package(JSONC REQUIRED)
find_package(CURL REQUIRED) find_package(CURL REQUIRED)
find_package(EXPAT REQUIRED) find_package(EXPAT REQUIRED)
find_package(CppUnit) find_package(CppUnit)
find_package(Boost REQUIRED)
IF ( CPPUNIT_FOUND ) IF ( CPPUNIT_FOUND )
set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} ) set( OPT_INCS ${CPPUNIT_INCLUDE_DIR} )

View File

@ -37,6 +37,11 @@ class Json ;
class OAuth2 ; class OAuth2 ;
class Path ; class Path ;
/*! \brief corresponds to an "entry" in the resource feed
This class is decodes an entry in the resource feed. It will stored the properties like
title, filename and ETag etc in member variables.
*/
class Entry class Entry
{ {
public : public :

View File

@ -85,14 +85,14 @@ public :
if ( map[child->m_type] != 0 ) if ( map[child->m_type] != 0 )
{ {
ImplVec& vec = *map[child->m_type] ; ImplVec& vec = *map[child->m_type] ;
iterator p = std::lower_bound( vec.begin(), vec.end(), child, Comp() ) ; std::pair<iterator,iterator> p =
std::equal_range( vec.begin(), vec.end(), child, Comp() ) ;
// cannot allow duplicate attribute nodes // cannot allow duplicate attribute nodes
if ( child->m_type == attr && p != vec.end() && if ( child->m_type == attr && p.first != p.second )
(*p)->m_type == attr && (*p)->m_name == child->m_name )
throw std::runtime_error( "duplicate attribute " + child->m_name ) ; throw std::runtime_error( "duplicate attribute " + child->m_name ) ;
vec.insert( p, child ) ; vec.insert( p.second, child ) ;
} }
m_children.push_back( child ) ; m_children.push_back( child ) ;
@ -107,12 +107,10 @@ public :
: Find( m_element, name ) ; : Find( m_element, name ) ;
} }
Impl* Find( ImplVec& map, const std::string& name ) std::pair<iterator,iterator> Children( const std::string& name )
{ {
Impl tmp( name , element ) ; Impl tmp( name , element ) ;
iterator i = std::lower_bound( map.begin(), map.end(), &tmp, Comp() ) ; return std::equal_range( m_element.begin(), m_element.end(), &tmp, Comp() ) ;
return i != map.end() && (*i)->m_name == name ? *i : 0 ;
} }
iterator Begin() iterator Begin()
@ -172,6 +170,15 @@ public :
} }
} ; } ;
private :
Impl* Find( ImplVec& map, const std::string& name )
{
Impl tmp( name , element ) ;
iterator i = std::lower_bound( map.begin(), map.end(), &tmp, Comp() ) ;
return i != map.end() && (*i)->m_name == name ? *i : 0 ;
}
private : private :
std::size_t m_ref ; std::size_t m_ref ;
@ -182,40 +189,13 @@ private :
ImplVec m_children ; ImplVec m_children ;
} ; } ;
Node::iterator::iterator( ) Node::iterator::iterator( ImplVec::iterator i ) : iterator_adaptor(i)
{ {
} }
Node::iterator::iterator( ImplVec::iterator it ) : m_it( it ) Node::iterator::reference Node::iterator::dereference() const
{ {
} return Node( (*base_reference())->AddRef() ) ;
Node::iterator::value_type Node::iterator::operator*() const
{
return Node( (*m_it)->AddRef() ) ;
}
Node::iterator Node::iterator::operator++()
{
m_it++ ;
return *this ;
}
Node::iterator Node::iterator::operator++(int)
{
iterator tmp( *this ) ;
++tmp ;
return tmp ;
}
bool Node::iterator::operator==( const iterator& i ) const
{
return m_it == i.m_it ;
}
bool Node::iterator::operator!=( const iterator& i ) const
{
return m_it != i.m_it ;
} }
Node::Node() : m_ptr( new Impl ) Node::Node() : m_ptr( new Impl )
@ -415,5 +395,11 @@ Node::Range Node::Attr() const
return std::make_pair( iterator(is.first), iterator(is.second) ) ; return std::make_pair( iterator(is.first), iterator(is.second) ) ;
} }
Node::Range Node::Children( const std::string& name ) const
{
std::pair<Impl::iterator, Impl::iterator> is = m_ptr->Children( name ) ;
return std::make_pair( iterator(is.first), iterator(is.second) ) ;
}
} } // end namespace } } // end namespace

View File

@ -19,6 +19,8 @@
#pragma once #pragma once
#include <boost/iterator_adaptors.hpp>
#include <iosfwd> #include <iosfwd>
#include <string> #include <string>
#include <vector> #include <vector>
@ -28,9 +30,13 @@ namespace gr { namespace xml {
class Node class Node
{ {
private :
class Impl ;
typedef std::vector<Impl*> ImplVec ;
public : public :
class iterator ; class iterator ;
typedef std::pair<Node::iterator, Node::iterator> Range ; typedef std::pair<iterator, iterator> Range ;
public : public :
Node() ; Node() ;
@ -66,34 +72,7 @@ public :
iterator end() const ; iterator end() const ;
Range Attr() const ; Range Attr() const ;
Range Children( const std::string& name ) const ;
private :
class Impl ;
typedef std::vector<Impl*> ImplVec ;
public :
class iterator
{
public :
iterator() ;
explicit iterator( std::vector< gr::xml::Node::Impl* >::iterator it ) ;
typedef Node value_type ;
typedef std::forward_iterator_tag iterator_category ;
typedef std::ptrdiff_t difference_type;
typedef Node* pointer;
typedef Node& reference;
value_type operator*() const ;
iterator operator++() ;
iterator operator++(int) ;
bool operator==( const iterator& i ) const ;
bool operator!=( const iterator& i ) const ;
private :
ImplVec::iterator m_it ;
} ;
private : private :
explicit Node( Impl *impl ) ; explicit Node( Impl *impl ) ;
@ -102,6 +81,23 @@ private :
Impl *m_ptr ; Impl *m_ptr ;
} ; } ;
class Node::iterator : public boost::iterator_adaptor<
Node::iterator,
Node::ImplVec::iterator,
Node,
boost::random_access_traversal_tag,
Node
>
{
public :
explicit iterator( ImplVec::iterator i ) ;
private :
friend class boost::iterator_core_access;
reference dereference() const ;
} ;
std::ostream& operator<<( std::ostream& os, const Node& node ) ; std::ostream& operator<<( std::ostream& os, const Node& node ) ;
} } // end of namespace } } // end of namespace

View File

@ -55,7 +55,7 @@ void NodeTest::TestTree( )
void NodeTest::TestParseFile( ) void NodeTest::TestParseFile( )
{ {
Node n = TreeBuilder::Parse( "<entry><link href=\"q\"><href>abc</href></link></entry>" ) ; Node n = TreeBuilder::Parse( "<entry><link href=\"q\"><href>abc</href></link><link></link></entry>" ) ;
CPPUNIT_ASSERT_EQUAL( std::string("entry"), n["entry"].Name() ) ; CPPUNIT_ASSERT_EQUAL( std::string("entry"), n["entry"].Name() ) ;
CPPUNIT_ASSERT_EQUAL( std::string("link"), n["entry"]["link"].Name() ) ; CPPUNIT_ASSERT_EQUAL( std::string("link"), n["entry"]["link"].Name() ) ;
CPPUNIT_ASSERT_EQUAL( std::string("q"), n["entry"]["link"]["@href"].Value() ) ; CPPUNIT_ASSERT_EQUAL( std::string("q"), n["entry"]["link"]["@href"].Value() ) ;
@ -70,7 +70,8 @@ void NodeTest::TestParseFile( )
++i ; ++i ;
} }
std::cout << n << std::endl ; Node::Range r = n["entry"].Children("link") ;
// CPPUNIT_ASSERT_EQUAL( 2, r.second - r.first ) ;
} }
} // end of namespace grut } // end of namespace grut