~alza/grive/grive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
	grive: an GPL program to sync a local directory with Google Drive
	Copyright (C) 2012  Wan Wai Ho

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation version 2
	of the License.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#include "NodeSet.hh"

#include "Error.hh"

#include <algorithm>

#include <iostream>

namespace gr { namespace xml {

NodeSet::NodeSet() :
	m_first( m_tmp.begin() ),
	m_last( m_tmp.end() )
{
}

NodeSet::NodeSet( iterator first, iterator last ) :
	m_first( first ),
	m_last( last )
{
}

NodeSet::NodeSet( const NodeSet& n ) :
	m_tmp( n.m_tmp ),
	m_first( m_tmp.begin() + (n.m_first - n.m_tmp.begin()) ),
	m_last( m_tmp.begin() + (n.m_last - n.m_tmp.begin()) )
{
}

NodeSet& NodeSet::operator=( const NodeSet& ns )
{
	NodeSet tmp( ns ) ;
	Swap( tmp ) ;
	return *this ;
}

void NodeSet::Swap( NodeSet& ns )
{
	m_tmp.Swap( ns.m_tmp ) ;
	std::swap( m_first, ns.m_first ) ;
	std::swap( m_last, ns.m_last ) ;
}

NodeSet::iterator NodeSet::begin() const
{
	return m_first ;
}

NodeSet::iterator NodeSet::end() const
{
	return m_last ;
}

/*!	This function search the members in the node set. If any members in the node
	set has a children named \a name , with value equal to \a value , it will
	be returned.
	\param	name	name to be found. prefix with '@' for attributes
	\param	value	value to be matched.
	\return	the node set contained all children nodes that matches \a name and \a value
*/
NodeSet NodeSet::Find( const std::string& name, const std::string& value ) const
{
	NodeSet result ;
	for ( iterator i = m_first ; i != m_last ; ++i )
	{
		NodeSet cand = (*i)[name] ;
		for ( iterator j = cand.m_first ; j != cand.m_last ; ++j )
		{
			if ( j->Value() == value )
			{
				result.Add( *i ) ;
				break ;
			}
		}
	}
	return result ;
}

void NodeSet::Add( const Node& n )
{
	// the tmp node is not used, that means the first,last iterators points to elsewhere
	if ( m_tmp.size() == 0 )
	{
		m_tmp.AddNode( m_first, m_last ) ;
	}

	m_tmp.AddNode( n ) ;
	
	// the iterators may be invalidated after adding the node
	m_first = m_tmp.begin() ;
	m_last  = m_tmp.end() ;
}

NodeSet NodeSet::operator[]( const std::string& name ) const
{
	for ( iterator i = m_first ; i != m_last ; ++i )
	{
		NodeSet r = (*i)[name] ;
		if ( !r.empty() )
			return r ;
	}
	return NodeSet() ;
}

Node NodeSet::front() const
{
	if ( empty() )
		throw Error() << expt::ErrMsg( "empty node set" ) ;
		
	return *m_first ;
}

NodeSet::operator std::string() const
{
	return empty() ? "" : front().Value() ;
}

bool NodeSet::operator==( const std::string& value ) const
{
	return operator std::string() == value ;
}

bool NodeSet::empty() const
{
	return m_first == m_last ;
}

std::size_t NodeSet::size() const
{
	return m_last - m_first ;
}

std::ostream& operator<<( std::ostream& os, const NodeSet& node )
{
	std::copy( node.begin(), node.end(), std::ostream_iterator<Node>(os, " ") ) ;
	return os ;
}

} } // end of namespace