1 
2 /******************************************************************************
3  *
4  *  file:  XorHandler.h
5  *
6  *  Copyright (c) 2003, Michael E. Smoot .
7  *  Copyright (c) 2004, Michael E. Smoot, Daniel Aarno.
8  *  All rights reverved.
9  *
10  *  See the file COPYING in the top directory of this distribution for
11  *  more information.
12  *
13  *  THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS
14  *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19  *  DEALINGS IN THE SOFTWARE.
20  *
21  *****************************************************************************/
22 
23 #ifndef TCLAP_XORHANDLER_H
24 #define TCLAP_XORHANDLER_H
25 
26 #include <tclap/Arg.h>
27 #include <string>
28 #include <vector>
29 #include <algorithm>
30 #include <iostream>
31 
32 namespace TCLAP {
33 
34 /**
35  * This class handles lists of Arg's that are to be XOR'd on the command
36  * line.  This is used by CmdLine and you shouldn't ever use it.
37  */
38 class XorHandler
39 {
40 	protected:
41 
42 		/**
43 		 * The list of of lists of Arg's to be or'd together.
44 		 */
45 		std::vector< std::vector<Arg*> > _orList;
46 
47 	public:
48 
49 		/**
50 		 * Constructor.  Does nothing.
51 		 */
XorHandler()52 		XorHandler( ) : _orList(std::vector< std::vector<Arg*> >()) {}
53 
54 		/**
55 		 * Add a list of Arg*'s that will be orred together.
56 		 * \param ors - list of Arg* that will be xor'd.
57 		 */
58 		void add( std::vector<Arg*>& ors );
59 
60 		/**
61 		 * Checks whether the specified Arg is in one of the xor lists and
62 		 * if it does match one, returns the size of the xor list that the
63 		 * Arg matched.  If the Arg matches, then it also sets the rest of
64 		 * the Arg's in the list. You shouldn't use this.
65 		 * \param a - The Arg to be checked.
66 		 */
67 		int check( const Arg* a );
68 
69 		/**
70 		 * Returns the XOR specific short usage.
71 		 */
72 		std::string shortUsage();
73 
74 		/**
75 		 * Prints the XOR specific long usage.
76 		 * \param os - Stream to print to.
77 		 */
78 		void printLongUsage(std::ostream& os);
79 
80 		/**
81 		 * Simply checks whether the Arg is contained in one of the arg
82 		 * lists.
83 		 * \param a - The Arg to be checked.
84 		 */
85 		bool contains( const Arg* a );
86 
87 		std::vector< std::vector<Arg*> >& getXorList();
88 
89 };
90 
91 
92 //////////////////////////////////////////////////////////////////////
93 //BEGIN XOR.cpp
94 //////////////////////////////////////////////////////////////////////
add(std::vector<Arg * > & ors)95 inline void XorHandler::add( std::vector<Arg*>& ors )
96 {
97 	_orList.push_back( ors );
98 }
99 
check(const Arg * a)100 inline int XorHandler::check( const Arg* a )
101 {
102 	// iterate over each XOR list
103 	for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
104 	{
105 		// if the XOR list contains the arg..
106 		ArgVectorIterator ait = std::find( _orList[i].begin(),
107 		                                   _orList[i].end(), a );
108 		if ( ait != _orList[i].end() )
109 		{
110 			// first check to see if a mutually exclusive switch
111 			// has not already been set
112 			for ( ArgVectorIterator it = _orList[i].begin();
113 				  it != _orList[i].end();
114 				  it++ )
115 				if ( a != (*it) && (*it)->isSet() )
116 					throw(CmdLineParseException(
117 					      "Mutually exclusive argument already set!",
118 					      (*it)->toString()));
119 
120 			// go through and set each arg that is not a
121 			for ( ArgVectorIterator it = _orList[i].begin();
122 				  it != _orList[i].end();
123 				  it++ )
124 				if ( a != (*it) )
125 					(*it)->xorSet();
126 
127 			// return the number of required args that have now been set
128 			if ( (*ait)->allowMore() )
129 				return 0;
130 			else
131 				return static_cast<int>(_orList[i].size());
132 		}
133 	}
134 
135 	if ( a->isRequired() )
136 		return 1;
137 	else
138 		return 0;
139 }
140 
contains(const Arg * a)141 inline bool XorHandler::contains( const Arg* a )
142 {
143 	for ( int i = 0; static_cast<unsigned int>(i) < _orList.size(); i++ )
144 		for ( ArgVectorIterator it = _orList[i].begin();
145 			  it != _orList[i].end();
146 			  it++ )
147 			if ( a == (*it) )
148 				return true;
149 
150 	return false;
151 }
152 
getXorList()153 inline std::vector< std::vector<Arg*> >& XorHandler::getXorList()
154 {
155 	return _orList;
156 }
157 
158 
159 
160 //////////////////////////////////////////////////////////////////////
161 //END XOR.cpp
162 //////////////////////////////////////////////////////////////////////
163 
164 } //namespace TCLAP
165 
166 #endif
167