CLAM-Development  1.4.0
Flags.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef _Flags_hxx_
23 #define _Flags_hxx_
24 
25 #include <bitset>
26 #include <string>
27 #include <iosfwd>
28 #include "Component.hxx"
29 // TODO: This is provisional to share the IllegalValue exception
30 #include "Enum.hxx"
31 
32 namespace CLAM {
33 
34 
40 class FlagsBase : public Component {
41 // Internal Types
42 public:
44  typedef unsigned int tValue;
46  typedef struct {tValue value; const char*name;} tFlagValue;
47 
48 // Attributes
49 protected:
55 
56 // Operations
57 public:
61  virtual unsigned int GetNFlags() const=0;
62  virtual void SetFlag(unsigned int whichOne, bool value)=0;
63  virtual bool IsSetFlag(unsigned int whichOne) const =0;
69  std::string GetFlagString(unsigned int whichOne) const throw (IllegalValue);
70 
76  unsigned int GetFlagPosition(const std::string & whichOne) const throw (IllegalValue);
77 
78  /*
79  * Stores component's subitems on the given Storage
80  * @param store The given storage where the subitem will be stored
81  * @see Storage
82  * @todo TODO: This method can throw and IllegalValue exception
83  */
84  virtual void StoreOn (Storage & storage) const;
85 
86  /*
87  * Loads component's subitems from the given Storage
88  * @param store The given storage where the subitem will be stored
89  * @see Storage
90  * @todo TODO: This method can throw and IllegalValue exception
91  */
92  virtual void LoadFrom (Storage & storage);
93 
94 // Debug
95 public:
106  inline bool CheckInvariant();
107 };
108 
109 std::istream & operator >> (std::istream & is, FlagsBase & f);
110 std::ostream & operator << (std::ostream & os, const FlagsBase & f);
111 
251 template <unsigned int N> class Flags : public FlagsBase, public std::bitset<N>
252 {
253 // Construction/Destruction
254 protected:
256  Flags(tFlagValue * names) : std::bitset<N>() {
257  mFlagValues=names;
258  };
262  Flags(tFlagValue * names, const Flags<N> &t) : std::bitset<N>() {
263  mFlagValues=names;
264  };
271  template <class T> Flags(tFlagValue * names,const T &t) : std::bitset<N>(t) {
272  mFlagValues=names;
273  };
282  template <class T1, class T2> Flags(tFlagValue * names,const T1 &t1,const T2 &t2) :
283  std::bitset<N>(t1, t2)
284  {
285  mFlagValues=names;
286  };
287 public:
289  virtual ~Flags () {};
290 
292  const char * GetClassName() const {return NULL;}
293 
294 // Operators
295 public:
296  virtual unsigned int GetNFlags () const {
297  return N;
298  }
299 protected:
300  virtual bool IsSetFlag(unsigned int whichOne) const {
301  return std::bitset<N>::test(whichOne);
302  }
303  virtual void SetFlag(unsigned int whichOne, bool value=true) {
304  this->set(whichOne, value);
305  }
306 
307 // Component Protocol
308 public:
315  virtual Component * Species () const = 0;
316 
317  virtual Component * DeepCopy () const {
318  Flags<N> * pe = (Flags<N>*)Species();
319  *pe=*this;
320  return pe;
321  }
322 
323  virtual Component * ShallowCopy () const {
324  Flags<N> * pe = (Flags<N>*)Species();
325  *pe=*this;
326  return pe;
327  }
328 
329 };
330 
331 //MRJ: Why this? There exists a fairly well known issue about
332 //VC6 support of template base classes, where polymorphism usual assumptions
333 //don't hold. In this case we introduce two proxy methods that
334 //just "inform" the compiler about what it has to do next... to promote
335 //the references to the derived class object into references to the
336 //base class. Sad but true. In discharge of MS guys this seems to be no
337 //longer needed in VC++ 7.1. We could have implemented the body of the methods
338 //inline on the header, but would have prevented us from using the compile-time
339 //saving usage of the <iosfwd> header.
340 
341 #ifdef _MSC_VER
342 template <unsigned int N>
343 std::istream & operator >> (std::istream & is, Flags<N> & f) {
344  return (is >> static_cast<FlagsBase&>(f) );
345 }
346 
347 template <unsigned int N>
348 std::ostream & operator << (std::ostream & os, const Flags<N> & f){
349  return (os << static_cast<const FlagsBase&>(f));
350 }
351 #endif //_MSC_VER
352 
353 }
354 
355 #endif//_Flags_hxx_
356