Enumeration.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_ENUMERATION_H_
00002 #define SimTK_SimTKCOMMON_ENUMERATION_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2007 Stanford University and the Authors.           *
00013  * Authors: Peter Eastman                                                     *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00035 #include "SimTKcommon/internal/common.h"
00036 #include "SimTKcommon/internal/ExceptionMacros.h"
00037 #include <vector>
00038 
00039 namespace SimTK {
00040 
00041 template <class T> class EnumerationSet;
00042 
00122 template <class T>
00123 class Enumeration {
00124 public:
00125     class iterator;
00129     int getIndex() const {
00130         init();
00131         return index;
00132     }
00136     const std::string getName() const {
00137         init();
00138         return name;
00139     }
00143     static int size() {
00144         return (int)updAllValues().size();
00145     }
00149     static const T& getValue(int index) {
00150         return *updAllValues()[index];
00151     }
00155     static iterator begin() {
00156         iterator first(0);
00157         return first;
00158     }
00162     static iterator end() {
00163         iterator last(size());
00164         return last;
00165     }
00166     Enumeration(const Enumeration<T>& copy) {
00167         init();
00168         index = copy.index;
00169         name = copy.name;
00170     }
00171     Enumeration<T>& operator=(const Enumeration<T>& copy) {
00172         init();
00173         index = copy.index;
00174         name = copy.name;
00175         return *this;
00176     }
00177     Enumeration<T>* operator&() {
00178         init();
00179         return this;
00180     }
00181     bool operator==(const Enumeration<T>& value) const {
00182         init();
00183         return (index == value.index);
00184     }
00185     bool operator!=(const Enumeration<T>& value) const {
00186         init();
00187         return (index != value.index);
00188     }
00189     operator int() const {
00190         return getIndex();
00191     }
00192     EnumerationSet<T> operator|(const EnumerationSet<T>& set) const {
00193         EnumerationSet<T> temp(*this);
00194         temp |= set;
00195         return temp;
00196     }
00197     EnumerationSet<T> operator&(const EnumerationSet<T>& set) const {
00198         EnumerationSet<T> temp(*this);
00199         temp &= set;
00200         return temp;
00201     }
00202     EnumerationSet<T> operator^(const EnumerationSet<T>& set) const {
00203         EnumerationSet<T> temp(*this);
00204         temp ^= set;
00205         return temp;
00206     }
00210     Enumeration<T> operator++() {
00211         assert (index < size()-1);
00212         ++index;
00213         name = getValue(index).name;
00214         return *this;
00215     }
00219     Enumeration<T> operator++(int) {
00220         assert (index < size()-1);
00221         Enumeration<T> current = *this;
00222         ++index;
00223         name = getValue(index).name;
00224         return current;
00225     }
00229     Enumeration<T> operator--() {
00230         assert (index > 0);
00231         --index;
00232         name = getValue(index).name;
00233         return *this;
00234     }
00238     Enumeration<T> operator--(int) {
00239         assert (index > 0);
00240         Enumeration<T> current = *this;
00241         --index;
00242         name = getValue(index).name;
00243         return current;
00244     }
00245 protected:
00246     // Default construction must not do anything to memory, because the static members
00247     // may already have been initialized before they get default constructed. If you
00248     // touch any data here, say by initializing "index" to -1, you may be wiping out a
00249     // static member constants. The constant will not then get fixed because the init() 
00250     // call will think it is already done.
00251     Enumeration() {
00252         init();
00253     }
00254     Enumeration(const T& thisElement, int index, const char* name) : index(index), name(name) {
00255         SimTK_ASSERT_ALWAYS(index == updAllValues().size(), "Indices must be consecutive ints starting from 0.");
00256         updAllValues().push_back(&thisElement);
00257     }
00258     static std::vector<const T*>& updAllValues() {
00259         static std::vector<const T*> allValues;
00260         return allValues;
00261     }
00262 private:
00263     int index;
00264     const char* name;
00271     static void init() {
00272         static bool isInitialized = false;
00273         if (!isInitialized) {
00274             isInitialized = true;
00275             T::initValues();
00276         }
00277     }
00278 };
00279 
00280 template <class T>
00281 std::ostream& operator<<(std::ostream& stream, const Enumeration<T>& value) {
00282     return stream << value.getName();
00283 }
00284 
00289 template <class T>
00290 class Enumeration<T>::iterator {
00291 public:
00292     Enumeration<T> operator*() {
00293         assert (index >= 0 && index < Enumeration<T>::size());
00294         return Enumeration<T>::getValue(index);
00295     }
00296     iterator operator++() {
00297         assert (index < Enumeration<T>::size());
00298         ++index;
00299         return *this;
00300     }
00301     iterator operator++(int) {
00302         assert (index < Enumeration<T>::size());
00303         iterator current = *this;
00304         ++index;
00305         return current;
00306     }
00307     bool operator==(const iterator& iter) {
00308         return (index == iter.index);
00309     }
00310     bool operator!=(const iterator& iter) {
00311         return (index != iter.index);
00312     }
00313 private:
00314     iterator(int index) : index(index) {
00315     }
00316     int index;
00317     friend class Enumeration<T>;
00318 };
00319 
00340 template <class T>
00341 class EnumerationSet {
00342 public:
00343     class iterator;
00347     EnumerationSet() {
00348         rep = new EnumerationSetRep();
00349     }
00353     EnumerationSet(const Enumeration<T>& value) {
00354         rep = new EnumerationSetRep(value);
00355     }
00359     EnumerationSet(const EnumerationSet<T>& set) {
00360         rep = new EnumerationSetRep(*set.rep);
00361     }
00362     ~EnumerationSet() {
00363         delete rep;
00364     }
00368     int size() const {
00369         return rep->size();
00370     }
00374     bool empty() const {
00375         return (rep->size() == 0);
00376     }
00380     bool contains(const Enumeration<T>& value) const {
00381         return rep->contains(value);
00382     }
00386     bool containsAll(const EnumerationSet<T>& set) const {
00387         return rep->containsAll(*set.rep);
00388     }
00392     bool containsAny(const EnumerationSet<T>& set) const {
00393         return rep->containsAny(*set.rep);
00394     }
00398     bool operator==(const EnumerationSet<T>& set) const {
00399         return *rep == *set.rep;
00400     }
00404     bool operator!=(const EnumerationSet<T>& set) const {
00405         return *rep != *set.rep;
00406     }
00410     void clear() {
00411         rep->clear();
00412     }
00416     iterator begin() {
00417         iterator first(this, 0);
00418         return first;
00419     }
00423     iterator end() {
00424         iterator last(this, Enumeration<T>::size());
00425         return last;
00426     }
00427     EnumerationSet<T>& operator=(const EnumerationSet<T>& set) {
00428         *rep = *set.rep;
00429         return *this;
00430     }
00431     EnumerationSet<T>& operator-=(const Enumeration<T>& value) {
00432         *rep -= value;
00433         return *this;
00434     }
00435     EnumerationSet<T>& operator-=(const EnumerationSet<T>& set) {
00436         *rep -= *set.rep;
00437         return *this;
00438     }
00439     EnumerationSet<T> operator-(const Enumeration<T>& value) const {
00440         EnumerationSet<T> temp(*this);
00441         temp -= value;
00442         return temp;
00443     }
00444     EnumerationSet<T> operator-(const EnumerationSet<T>& set) const {
00445         EnumerationSet<T> temp(*this);
00446         temp -= set;
00447         return temp;
00448     }
00449     EnumerationSet<T>& operator|=(const EnumerationSet<T>& set) {
00450         *rep |= *set.rep;
00451         return *this;
00452     }
00453     EnumerationSet<T> operator|(const EnumerationSet<T>& set) const {
00454         EnumerationSet<T> temp(*this);
00455         temp |= set;
00456         return temp;
00457     }
00458     EnumerationSet<T>& operator&=(const EnumerationSet<T>& set) {
00459         *rep &= *set.rep;
00460         return *this;
00461     }
00462     EnumerationSet<T> operator&(const EnumerationSet<T>& set) const {
00463         EnumerationSet<T> temp(*this);
00464         temp &= set;
00465         return temp;
00466     }
00467     EnumerationSet<T>& operator^=(const EnumerationSet<T>& set) {
00468         *rep ^= *set.rep;
00469         return *this;
00470     }
00471     EnumerationSet<T> operator^(const EnumerationSet<T>& set) const {
00472         EnumerationSet<T> temp(*this);
00473         temp ^= set;
00474         return temp;
00475     }
00476     EnumerationSet<T> operator~() const {
00477         EnumerationSet<T> temp(*this);
00478         temp.rep->invert();
00479         return temp;
00480     }
00481 private:
00482     class EnumerationSetRep;
00483     EnumerationSetRep* rep;
00484 };
00485 
00490 template <class T>
00491 class EnumerationSet<T>::EnumerationSetRep {
00492 public:
00496     EnumerationSetRep() {
00497         init();
00498     }
00502     EnumerationSetRep(const Enumeration<T>& value) {
00503         init();
00504         flags[word(value)] = mask(value);
00505         numElements = 1;
00506     }
00510     EnumerationSetRep(const EnumerationSetRep& set) {
00511         init();
00512         *this = set;
00513     }
00514     ~EnumerationSetRep() {
00515         delete[] flags;
00516     }
00520     int size() const {
00521         if (numElements == -1) {
00522             numElements = 0;
00523             for (int i = 0; i < words; ++i) {
00524                 int temp = flags[i];
00525                 while (temp != 0) {
00526                     ++numElements;
00527                     temp &= temp-1;
00528                 }
00529             }
00530         }
00531         return numElements;
00532     }
00536     bool contains(const Enumeration<T>& value) const {
00537         return ((flags[word(value)] & mask(value)) != 0);
00538     }
00542     bool containsAll(const EnumerationSetRep& set) const {
00543         for (int i = 0; i < words; ++i)
00544             if ((flags[i] & set.flags[i]) != set.flags[i])
00545                 return false;
00546         return true;
00547     }
00551     bool containsAny(const EnumerationSetRep& set) const {
00552         for (int i = 0; i < words; ++i)
00553             if ((flags[i] & set.flags[i]) != 0)
00554                 return true;
00555         return false;
00556     }
00560     bool operator==(const EnumerationSetRep& set) const {
00561         for (int i = 0; i < words; ++i)
00562             if (flags[i] != set.flags[i])
00563                 return false;
00564         return true;
00565     }
00569     bool operator!=(const EnumerationSetRep& set) const {
00570         for (int i = 0; i < words; ++i)
00571             if (flags[i] != set.flags[i])
00572                 return true;
00573         return false;
00574     }
00578     void clear() {
00579         for (int i = 0; i < words; ++i)
00580             flags[i] = 0;
00581         numElements = 0;
00582     }
00583     EnumerationSetRep& operator=(const EnumerationSetRep& set) {
00584         for (int i = 0; i < words; ++i)
00585             flags[i] = set.flags[i];
00586         numElements = set.numElements;
00587         return *this;
00588     }
00589     EnumerationSetRep& operator-=(const Enumeration<T>& value) {
00590         flags[word(value)] &= ~mask(value);
00591         numElements = -1;
00592         return *this;
00593     }
00594     EnumerationSetRep& operator-=(const EnumerationSetRep& set) {
00595         for (int i = 0; i < words; ++i)
00596             flags[i] &= ~set.flags[i];
00597         numElements = -1;
00598         return *this;
00599     }
00600     EnumerationSetRep& operator|=(const EnumerationSetRep& set) {
00601         for (int i = 0; i < words; ++i)
00602             flags[i] |= set.flags[i];
00603         numElements = -1;
00604         return *this;
00605     }
00606     EnumerationSetRep& operator&=(const EnumerationSetRep& set) {
00607         for (int i = 0; i < words; ++i)
00608             flags[i] &= set.flags[i];
00609         numElements = -1;
00610         return *this;
00611     }
00612     EnumerationSetRep& operator^=(const EnumerationSetRep& set) {
00613         for (int i = 0; i < words; ++i)
00614             flags[i] ^= set.flags[i];
00615         numElements = -1;
00616         return *this;
00617     }
00618     void invert() const {
00619         for (int i = 0; i < words-1; ++i)
00620             flags[i] = -1-flags[i];
00621         flags[words-1] = (1<<T::size()%BITS_PER_WORD)-1-flags[words-1];
00622         numElements = -1;
00623     }
00624 private:
00628     void init() {
00629         numElements = -1;
00630         words = (T::size()+BITS_PER_WORD-1)/BITS_PER_WORD;
00631         flags = new int[words];
00632         for (int i = 0; i < words; ++i)
00633             flags[i] = 0;
00634     }
00639     int mask(const Enumeration<T>& value) const {
00640         return 1<<(value.getIndex()%BITS_PER_WORD);
00641     }
00645     int word(const Enumeration<T>& value) const {
00646         return value.getIndex()/BITS_PER_WORD;
00647     }
00648     int* flags;
00649     short words;
00650     mutable short numElements;
00651     static const int BITS_PER_WORD = 8*sizeof(int);
00652 };
00653 
00658 template <class T>
00659 class EnumerationSet<T>::iterator {
00660 public:
00661     Enumeration<T> operator*() {
00662         assert (index >= 0 && index < Enumeration<T>::size());
00663         return Enumeration<T>::getValue(index);
00664     }
00665     iterator operator++() {
00666         assert (index < Enumeration<T>::size());
00667         ++index;
00668         findNextElement();
00669         return *this;
00670     }
00671     iterator operator++(int) {
00672         assert (index < Enumeration<T>::size());
00673         iterator current = *this;
00674         ++index;
00675         findNextElement();
00676         return current;
00677     }
00678     bool operator==(const iterator& iter) {
00679         return (set == iter.set && index == iter.index);
00680     }
00681     bool operator!=(const iterator& iter) {
00682         return (set != iter.set || index != iter.index);
00683     }
00684 private:
00685     iterator(EnumerationSet<T>* set, int index) : set(set), index(index) {
00686         findNextElement();
00687     }
00688     void findNextElement() {
00689         while (index < Enumeration<T>::size() && !set->contains(Enumeration<T>::getValue(index)))
00690             ++index;
00691     }
00692     int index;
00693     EnumerationSet<T>* set;
00694     friend class EnumerationSet<T>;
00695 };
00696 
00697 } // namespace SimTK
00698 
00699 #endif // SimTK_SimTKCOMMON_ENUMERATION_H_

Generated by  doxygen 1.6.2