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 
00118 template <class T>
00119 class Enumeration {
00120 public:
00121     class iterator;
00125     int getIndex() const {
00126         init();
00127         return index;
00128     }
00132     const std::string getName() const {
00133         init();
00134         return name;
00135     }
00139     static int size() {
00140         return updAllValues().size();
00141     }
00145     static const T& getValue(int index) {
00146         return *updAllValues()[index];
00147     }
00151     static iterator begin() {
00152         iterator first(0);
00153         return first;
00154     }
00158     static iterator end() {
00159         iterator last(size());
00160         return last;
00161     }
00162     Enumeration(const Enumeration<T>& copy) {
00163         init();
00164         index = copy.index;
00165         name = copy.name;
00166     }
00167     Enumeration<T>& operator=(const Enumeration<T>& copy) {
00168         init();
00169         index = copy.index;
00170         name = copy.name;
00171         return *this;
00172     }
00173     Enumeration<T>* operator&() {
00174         init();
00175         return this;
00176     }
00177     bool operator==(const Enumeration<T>& value) const {
00178         init();
00179         return (index == value.index);
00180     }
00181     bool operator!=(const Enumeration<T>& value) const {
00182         init();
00183         return (index != value.index);
00184     }
00185     operator int() const {
00186         return getIndex();
00187     }
00188     EnumerationSet<T> operator|(const EnumerationSet<T>& set) const {
00189         EnumerationSet<T> temp(*this);
00190         temp |= set;
00191         return temp;
00192     }
00193     EnumerationSet<T> operator&(const EnumerationSet<T>& set) const {
00194         EnumerationSet<T> temp(*this);
00195         temp &= set;
00196         return temp;
00197     }
00198     EnumerationSet<T> operator^(const EnumerationSet<T>& set) const {
00199         EnumerationSet<T> temp(*this);
00200         temp ^= set;
00201         return temp;
00202     }
00206     Enumeration<T> operator++() {
00207         assert (index < size()-1);
00208         ++index;
00209         name = getValue(index).name;
00210         return *this;
00211     }
00215     Enumeration<T> operator++(int) {
00216         assert (index < size()-1);
00217         Enumeration<T> current = *this;
00218         ++index;
00219         name = getValue(index).name;
00220         return current;
00221     }
00225     Enumeration<T> operator--() {
00226         assert (index > 0);
00227         --index;
00228         name = getValue(index).name;
00229         return *this;
00230     }
00234     Enumeration<T> operator--(int) {
00235         assert (index > 0);
00236         Enumeration<T> current = *this;
00237         --index;
00238         name = getValue(index).name;
00239         return current;
00240     }
00241 protected:
00242     Enumeration() {
00243         init();
00244     }
00245     Enumeration(const T& thisElement, int index, const char* name) : index(index), name(name) {
00246         SimTK_ASSERT_ALWAYS(index == updAllValues().size(), "Indices must be consecutive ints starting from 0.");
00247         updAllValues().push_back(&thisElement);
00248     }
00249     static std::vector<const T*>& updAllValues() {
00250         static std::vector<const T*> allValues;
00251         return allValues;
00252     }
00253 private:
00254     int index;
00255     const char* name;
00262     static void init() {
00263         static bool isInitialized = false;
00264         if (!isInitialized) {
00265             isInitialized = true;
00266             T::initValues();
00267         }
00268     }
00269 };
00270 
00271 template <class T>
00272 std::ostream& operator<<(std::ostream& stream, const Enumeration<T>& value) {
00273     return stream << value.getName();
00274 }
00275 
00280 template <class T>
00281 class Enumeration<T>::iterator {
00282 public:
00283     Enumeration<T> operator*() {
00284         assert (index >= 0 && index < Enumeration<T>::size());
00285         return Enumeration<T>::getValue(index);
00286     }
00287     iterator operator++() {
00288         assert (index < Enumeration<T>::size());
00289         ++index;
00290         return *this;
00291     }
00292     iterator operator++(int) {
00293         assert (index < Enumeration<T>::size());
00294         iterator current = *this;
00295         ++index;
00296         return current;
00297     }
00298     bool operator==(const iterator& iter) {
00299         return (index == iter.index);
00300     }
00301     bool operator!=(const iterator& iter) {
00302         return (index != iter.index);
00303     }
00304 private:
00305     iterator(int index) : index(index) {
00306     }
00307     int index;
00308     friend class Enumeration<T>;
00309 };
00310 
00331 template <class T>
00332 class EnumerationSet {
00333 public:
00334     class iterator;
00338     EnumerationSet() {
00339         rep = new EnumerationSetRep();
00340     }
00344     EnumerationSet(const Enumeration<T>& value) {
00345         rep = new EnumerationSetRep(value);
00346     }
00350     EnumerationSet(const EnumerationSet<T>& set) {
00351         rep = new EnumerationSetRep(*set.rep);
00352     }
00353     ~EnumerationSet() {
00354         delete rep;
00355     }
00359     int size() const {
00360         return rep->size();
00361     }
00365     bool empty() const {
00366         return (rep->size() == 0);
00367     }
00371     bool contains(const Enumeration<T>& value) const {
00372         return rep->contains(value);
00373     }
00377     bool containsAll(const EnumerationSet<T>& set) const {
00378         return rep->containsAll(*set.rep);
00379     }
00383     bool containsAny(const EnumerationSet<T>& set) const {
00384         return rep->containsAny(*set.rep);
00385     }
00389     bool operator==(const EnumerationSet<T>& set) const {
00390         return *rep == *set.rep;
00391     }
00395     bool operator!=(const EnumerationSet<T>& set) const {
00396         return *rep != *set.rep;
00397     }
00401     void clear() {
00402         rep->clear();
00403     }
00407     iterator begin() {
00408         iterator first(this, 0);
00409         return first;
00410     }
00414     iterator end() {
00415         iterator last(this, Enumeration<T>::size());
00416         return last;
00417     }
00418     EnumerationSet<T>& operator=(const EnumerationSet<T>& set) {
00419         *rep = *set.rep;
00420         return *this;
00421     }
00422     EnumerationSet<T>& operator-=(const Enumeration<T>& value) {
00423         *rep -= value;
00424         return *this;
00425     }
00426     EnumerationSet<T>& operator-=(const EnumerationSet<T>& set) {
00427         *rep -= *set.rep;
00428         return *this;
00429     }
00430     EnumerationSet<T> operator-(const Enumeration<T>& value) const {
00431         EnumerationSet<T> temp(*this);
00432         temp -= value;
00433         return temp;
00434     }
00435     EnumerationSet<T> operator-(const EnumerationSet<T>& set) const {
00436         EnumerationSet<T> temp(*this);
00437         temp -= set;
00438         return temp;
00439     }
00440     EnumerationSet<T>& operator|=(const EnumerationSet<T>& set) {
00441         *rep |= *set.rep;
00442         return *this;
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 {
00468         EnumerationSet<T> temp(*this);
00469         temp.rep->invert();
00470         return temp;
00471     }
00472 private:
00473     class EnumerationSetRep;
00474     EnumerationSetRep* rep;
00475 };
00476 
00481 template <class T>
00482 class EnumerationSet<T>::EnumerationSetRep {
00483 public:
00487     EnumerationSetRep() {
00488         init();
00489     }
00493     EnumerationSetRep(const Enumeration<T>& value) {
00494         init();
00495         flags[word(value)] = mask(value);
00496         numElements = 1;
00497     }
00501     EnumerationSetRep(const EnumerationSetRep& set) {
00502         init();
00503         *this = set;
00504     }
00505     ~EnumerationSetRep() {
00506         delete[] flags;
00507     }
00511     int size() const {
00512         if (numElements == -1) {
00513             numElements = 0;
00514             for (int i = 0; i < words; ++i) {
00515                 int temp = flags[i];
00516                 while (temp != 0) {
00517                     ++numElements;
00518                     temp &= temp-1;
00519                 }
00520             }
00521         }
00522         return numElements;
00523     }
00527     bool contains(const Enumeration<T>& value) const {
00528         return ((flags[word(value)] & mask(value)) != 0);
00529     }
00533     bool containsAll(const EnumerationSetRep& set) const {
00534         for (int i = 0; i < words; ++i)
00535             if ((flags[i] & set.flags[i]) != set.flags[i])
00536                 return false;
00537         return true;
00538     }
00542     bool containsAny(const EnumerationSetRep& set) const {
00543         for (int i = 0; i < words; ++i)
00544             if ((flags[i] & set.flags[i]) != 0)
00545                 return true;
00546         return false;
00547     }
00551     bool operator==(const EnumerationSetRep& set) const {
00552         for (int i = 0; i < words; ++i)
00553             if (flags[i] != set.flags[i])
00554                 return false;
00555         return true;
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 true;
00564         return false;
00565     }
00569     void clear() {
00570         for (int i = 0; i < words; ++i)
00571             flags[i] = 0;
00572         numElements = 0;
00573     }
00574     EnumerationSetRep& operator=(const EnumerationSetRep& set) {
00575         for (int i = 0; i < words; ++i)
00576             flags[i] = set.flags[i];
00577         numElements = set.numElements;
00578         return *this;
00579     }
00580     EnumerationSetRep& operator-=(const Enumeration<T>& value) {
00581         flags[word(value)] &= ~mask(value);
00582         numElements = -1;
00583         return *this;
00584     }
00585     EnumerationSetRep& operator-=(const EnumerationSetRep& set) {
00586         for (int i = 0; i < words; ++i)
00587             flags[i] &= ~set.flags[i];
00588         numElements = -1;
00589         return *this;
00590     }
00591     EnumerationSetRep& operator|=(const EnumerationSetRep& set) {
00592         for (int i = 0; i < words; ++i)
00593             flags[i] |= set.flags[i];
00594         numElements = -1;
00595         return *this;
00596     }
00597     EnumerationSetRep& operator&=(const EnumerationSetRep& set) {
00598         for (int i = 0; i < words; ++i)
00599             flags[i] &= set.flags[i];
00600         numElements = -1;
00601         return *this;
00602     }
00603     EnumerationSetRep& operator^=(const EnumerationSetRep& set) {
00604         for (int i = 0; i < words; ++i)
00605             flags[i] ^= set.flags[i];
00606         numElements = -1;
00607         return *this;
00608     }
00609     void invert() const {
00610         for (int i = 0; i < words-1; ++i)
00611             flags[i] = -1-flags[i];
00612         flags[words-1] = (1<<T::size()%BITS_PER_WORD)-1-flags[words-1];
00613         numElements = -1;
00614     }
00615 private:
00619     void init() {
00620         numElements = -1;
00621         words = (T::size()+BITS_PER_WORD-1)/BITS_PER_WORD;
00622         flags = new int[words];
00623         for (int i = 0; i < words; ++i)
00624             flags[i] = 0;
00625     }
00630     int mask(const Enumeration<T>& value) const {
00631         return 1<<(value.getIndex()%BITS_PER_WORD);
00632     }
00636     int word(const Enumeration<T>& value) const {
00637         return value.getIndex()/BITS_PER_WORD;
00638     }
00639     int* flags;
00640     short words;
00641     mutable short numElements;
00642     static const int BITS_PER_WORD = 8*sizeof(int);
00643 };
00644 
00649 template <class T>
00650 class EnumerationSet<T>::iterator {
00651 public:
00652     Enumeration<T> operator*() {
00653         assert (index >= 0 && index < Enumeration<T>::size());
00654         return Enumeration<T>::getValue(index);
00655     }
00656     iterator operator++() {
00657         assert (index < Enumeration<T>::size());
00658         ++index;
00659         findNextElement();
00660         return *this;
00661     }
00662     iterator operator++(int) {
00663         assert (index < Enumeration<T>::size());
00664         iterator current = *this;
00665         ++index;
00666         findNextElement();
00667         return current;
00668     }
00669     bool operator==(const iterator& iter) {
00670         return (set == iter.set && index == iter.index);
00671     }
00672     bool operator!=(const iterator& iter) {
00673         return (set != iter.set || index != iter.index);
00674     }
00675 private:
00676     iterator(EnumerationSet<T>* set, int index) : set(set), index(index) {
00677         findNextElement();
00678     }
00679     void findNextElement() {
00680         while (index < Enumeration<T>::size() && !set->contains(Enumeration<T>::getValue(index)))
00681             ++index;
00682     }
00683     int index;
00684     EnumerationSet<T>* set;
00685     friend class EnumerationSet<T>;
00686 };
00687 
00688 } // namespace SimTK
00689 
00690 #endif // SimTK_SimTKCOMMON_ENUMERATION_H_

Generated on Thu Feb 28 01:34:28 2008 for SimTKcommon by  doxygen 1.4.7