Simbody

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 "SimTKcommon/internal/Array.h"
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     // Address operator should usually return a Stage*, not a Enumeration<Stage>*
00178     // The previous Enumeration<Stage>* return value was causing a problem in 
00179     // boost.python headers, in a statment equivalent to:
00180     //    "Stage* const p = &const_cast<Stage&>((Stage const&)stage);"
00181     // Which looks innocent, except that it fails to compile when that first "&" 
00182     // generated an Enumeration<Stage>* instead of a Stage*.  Wrapping now works with
00183     // this method returning a T*.
00184     T* operator&() {
00185         init();
00186         return static_cast<T*>(this);
00187     }
00188     bool operator==(const Enumeration<T>& value) const {
00189         init();
00190         return (index == value.index);
00191     }
00192     bool operator!=(const Enumeration<T>& value) const {
00193         init();
00194         return (index != value.index);
00195     }
00196     operator int() const {
00197         return getIndex();
00198     }
00199     EnumerationSet<T> operator|(const EnumerationSet<T>& set) const {
00200         EnumerationSet<T> temp(*this);
00201         temp |= set;
00202         return temp;
00203     }
00204     EnumerationSet<T> operator&(const EnumerationSet<T>& set) const {
00205         EnumerationSet<T> temp(*this);
00206         temp &= set;
00207         return temp;
00208     }
00209     EnumerationSet<T> operator^(const EnumerationSet<T>& set) const {
00210         EnumerationSet<T> temp(*this);
00211         temp ^= set;
00212         return temp;
00213     }
00217     Enumeration<T> operator++() {
00218         assert (index < size()-1);
00219         ++index;
00220         name = getValue(index).name;
00221         return *this;
00222     }
00226     Enumeration<T> operator++(int) {
00227         assert (index < size()-1);
00228         Enumeration<T> current = *this;
00229         ++index;
00230         name = getValue(index).name;
00231         return current;
00232     }
00236     Enumeration<T> operator--() {
00237         assert (index > 0);
00238         --index;
00239         name = getValue(index).name;
00240         return *this;
00241     }
00245     Enumeration<T> operator--(int) {
00246         assert (index > 0);
00247         Enumeration<T> current = *this;
00248         --index;
00249         name = getValue(index).name;
00250         return current;
00251     }
00252 protected:
00253     // Default construction must not do anything to memory, because the static members
00254     // may already have been initialized before they get default constructed. If you
00255     // touch any data here, say by initializing "index" to -1, you may be wiping out a
00256     // static member constants. The constant will not then get fixed because the init() 
00257     // call will think it is already done.
00258     Enumeration() {
00259         init();
00260     }
00261     Enumeration(const T& thisElement, int index, const char* name) : index(index), name(name) {
00262         SimTK_ASSERT_ALWAYS(index == updAllValues().size(), "Indices must be consecutive ints starting from 0.");
00263         updAllValues().push_back(&thisElement);
00264     }
00265     static Array_<const T*>& updAllValues() {
00266         static Array_<const T*> allValues;
00267         return allValues;
00268     }
00269 private:
00270     int index;
00271     const char* name;
00278     static void init() {
00279         static bool isInitialized = false;
00280         if (!isInitialized) {
00281             isInitialized = true;
00282             T::initValues();
00283         }
00284     }
00285 };
00286 
00287 template <class T>
00288 std::ostream& operator<<(std::ostream& stream, const Enumeration<T>& value) {
00289     return stream << value.getName();
00290 }
00291 
00296 template <class T>
00297 class Enumeration<T>::iterator {
00298 public:
00299     Enumeration<T> operator*() {
00300         assert (index >= 0 && index < Enumeration<T>::size());
00301         return Enumeration<T>::getValue(index);
00302     }
00303     iterator operator++() {
00304         assert (index < Enumeration<T>::size());
00305         ++index;
00306         return *this;
00307     }
00308     iterator operator++(int) {
00309         assert (index < Enumeration<T>::size());
00310         iterator current = *this;
00311         ++index;
00312         return current;
00313     }
00314     bool operator==(const iterator& iter) {
00315         return (index == iter.index);
00316     }
00317     bool operator!=(const iterator& iter) {
00318         return (index != iter.index);
00319     }
00320 private:
00321     iterator(int index) : index(index) {
00322     }
00323     int index;
00324     friend class Enumeration<T>;
00325 };
00326 
00347 template <class T>
00348 class EnumerationSet {
00349 public:
00350     class iterator;
00354     EnumerationSet() {
00355         rep = new EnumerationSetRep();
00356     }
00360     EnumerationSet(const Enumeration<T>& value) {
00361         rep = new EnumerationSetRep(value);
00362     }
00366     EnumerationSet(const EnumerationSet<T>& set) {
00367         rep = new EnumerationSetRep(*set.rep);
00368     }
00369     ~EnumerationSet() {
00370         delete rep;
00371     }
00375     int size() const {
00376         return rep->size();
00377     }
00381     bool empty() const {
00382         return (rep->size() == 0);
00383     }
00387     bool contains(const Enumeration<T>& value) const {
00388         return rep->contains(value);
00389     }
00393     bool containsAll(const EnumerationSet<T>& set) const {
00394         return rep->containsAll(*set.rep);
00395     }
00399     bool containsAny(const EnumerationSet<T>& set) const {
00400         return rep->containsAny(*set.rep);
00401     }
00405     bool operator==(const EnumerationSet<T>& set) const {
00406         return *rep == *set.rep;
00407     }
00411     bool operator!=(const EnumerationSet<T>& set) const {
00412         return *rep != *set.rep;
00413     }
00417     void clear() {
00418         rep->clear();
00419     }
00423     iterator begin() {
00424         iterator first(this, 0);
00425         return first;
00426     }
00430     iterator end() {
00431         iterator last(this, Enumeration<T>::size());
00432         return last;
00433     }
00434     EnumerationSet<T>& operator=(const EnumerationSet<T>& set) {
00435         *rep = *set.rep;
00436         return *this;
00437     }
00438     EnumerationSet<T>& operator-=(const Enumeration<T>& value) {
00439         *rep -= value;
00440         return *this;
00441     }
00442     EnumerationSet<T>& operator-=(const EnumerationSet<T>& set) {
00443         *rep -= *set.rep;
00444         return *this;
00445     }
00446     EnumerationSet<T> operator-(const Enumeration<T>& value) const {
00447         EnumerationSet<T> temp(*this);
00448         temp -= value;
00449         return temp;
00450     }
00451     EnumerationSet<T> operator-(const EnumerationSet<T>& set) const {
00452         EnumerationSet<T> temp(*this);
00453         temp -= set;
00454         return temp;
00455     }
00456     EnumerationSet<T>& operator|=(const EnumerationSet<T>& set) {
00457         *rep |= *set.rep;
00458         return *this;
00459     }
00460     EnumerationSet<T> operator|(const EnumerationSet<T>& set) const {
00461         EnumerationSet<T> temp(*this);
00462         temp |= set;
00463         return temp;
00464     }
00465     EnumerationSet<T>& operator&=(const EnumerationSet<T>& set) {
00466         *rep &= *set.rep;
00467         return *this;
00468     }
00469     EnumerationSet<T> operator&(const EnumerationSet<T>& set) const {
00470         EnumerationSet<T> temp(*this);
00471         temp &= set;
00472         return temp;
00473     }
00474     EnumerationSet<T>& operator^=(const EnumerationSet<T>& set) {
00475         *rep ^= *set.rep;
00476         return *this;
00477     }
00478     EnumerationSet<T> operator^(const EnumerationSet<T>& set) const {
00479         EnumerationSet<T> temp(*this);
00480         temp ^= set;
00481         return temp;
00482     }
00483     EnumerationSet<T> operator~() const {
00484         EnumerationSet<T> temp(*this);
00485         temp.rep->invert();
00486         return temp;
00487     }
00488 private:
00489     class EnumerationSetRep;
00490     EnumerationSetRep* rep;
00491 };
00492 
00497 template <class T>
00498 class EnumerationSet<T>::EnumerationSetRep {
00499 public:
00503     EnumerationSetRep() {
00504         init();
00505     }
00509     EnumerationSetRep(const Enumeration<T>& value) {
00510         init();
00511         flags[word(value)] = mask(value);
00512         numElements = 1;
00513     }
00517     EnumerationSetRep(const EnumerationSetRep& set) {
00518         init();
00519         *this = set;
00520     }
00521     ~EnumerationSetRep() {
00522         delete[] flags;
00523     }
00527     int size() const {
00528         if (numElements == -1) {
00529             numElements = 0;
00530             for (int i = 0; i < words; ++i) {
00531                 int temp = flags[i];
00532                 while (temp != 0) {
00533                     ++numElements;
00534                     temp &= temp-1;
00535                 }
00536             }
00537         }
00538         return numElements;
00539     }
00543     bool contains(const Enumeration<T>& value) const {
00544         return ((flags[word(value)] & mask(value)) != 0);
00545     }
00549     bool containsAll(const EnumerationSetRep& set) const {
00550         for (int i = 0; i < words; ++i)
00551             if ((flags[i] & set.flags[i]) != set.flags[i])
00552                 return false;
00553         return true;
00554     }
00558     bool containsAny(const EnumerationSetRep& set) const {
00559         for (int i = 0; i < words; ++i)
00560             if ((flags[i] & set.flags[i]) != 0)
00561                 return true;
00562         return false;
00563     }
00567     bool operator==(const EnumerationSetRep& set) const {
00568         for (int i = 0; i < words; ++i)
00569             if (flags[i] != set.flags[i])
00570                 return false;
00571         return true;
00572     }
00576     bool operator!=(const EnumerationSetRep& set) const {
00577         for (int i = 0; i < words; ++i)
00578             if (flags[i] != set.flags[i])
00579                 return true;
00580         return false;
00581     }
00585     void clear() {
00586         for (int i = 0; i < words; ++i)
00587             flags[i] = 0;
00588         numElements = 0;
00589     }
00590     EnumerationSetRep& operator=(const EnumerationSetRep& set) {
00591         for (int i = 0; i < words; ++i)
00592             flags[i] = set.flags[i];
00593         numElements = set.numElements;
00594         return *this;
00595     }
00596     EnumerationSetRep& operator-=(const Enumeration<T>& value) {
00597         flags[word(value)] &= ~mask(value);
00598         numElements = -1;
00599         return *this;
00600     }
00601     EnumerationSetRep& operator-=(const EnumerationSetRep& set) {
00602         for (int i = 0; i < words; ++i)
00603             flags[i] &= ~set.flags[i];
00604         numElements = -1;
00605         return *this;
00606     }
00607     EnumerationSetRep& operator|=(const EnumerationSetRep& set) {
00608         for (int i = 0; i < words; ++i)
00609             flags[i] |= set.flags[i];
00610         numElements = -1;
00611         return *this;
00612     }
00613     EnumerationSetRep& operator&=(const EnumerationSetRep& set) {
00614         for (int i = 0; i < words; ++i)
00615             flags[i] &= set.flags[i];
00616         numElements = -1;
00617         return *this;
00618     }
00619     EnumerationSetRep& operator^=(const EnumerationSetRep& set) {
00620         for (int i = 0; i < words; ++i)
00621             flags[i] ^= set.flags[i];
00622         numElements = -1;
00623         return *this;
00624     }
00625     void invert() const {
00626         for (int i = 0; i < words-1; ++i)
00627             flags[i] = -1-flags[i];
00628         flags[words-1] = (1<<T::size()%BITS_PER_WORD)-1-flags[words-1];
00629         numElements = -1;
00630     }
00631 private:
00635     void init() {
00636         numElements = -1;
00637         words = (T::size()+BITS_PER_WORD-1)/BITS_PER_WORD;
00638         flags = new int[words];
00639         for (int i = 0; i < words; ++i)
00640             flags[i] = 0;
00641     }
00646     int mask(const Enumeration<T>& value) const {
00647         return 1<<(value.getIndex()%BITS_PER_WORD);
00648     }
00652     int word(const Enumeration<T>& value) const {
00653         return value.getIndex()/BITS_PER_WORD;
00654     }
00655     int* flags;
00656     short words;
00657     mutable short numElements;
00658     static const int BITS_PER_WORD = 8*sizeof(int);
00659 };
00660 
00665 template <class T>
00666 class EnumerationSet<T>::iterator {
00667 public:
00668     Enumeration<T> operator*() {
00669         assert (index >= 0 && index < Enumeration<T>::size());
00670         return Enumeration<T>::getValue(index);
00671     }
00672     iterator operator++() {
00673         assert (index < Enumeration<T>::size());
00674         ++index;
00675         findNextElement();
00676         return *this;
00677     }
00678     iterator operator++(int) {
00679         assert (index < Enumeration<T>::size());
00680         iterator current = *this;
00681         ++index;
00682         findNextElement();
00683         return current;
00684     }
00685     bool operator==(const iterator& iter) {
00686         return (set == iter.set && index == iter.index);
00687     }
00688     bool operator!=(const iterator& iter) {
00689         return (set != iter.set || index != iter.index);
00690     }
00691 private:
00692     iterator(EnumerationSet<T>* set, int index) : set(set), index(index) {
00693         findNextElement();
00694     }
00695     void findNextElement() {
00696         while (index < Enumeration<T>::size() && !set->contains(Enumeration<T>::getValue(index)))
00697             ++index;
00698     }
00699     int index;
00700     EnumerationSet<T>* set;
00701     friend class EnumerationSet<T>;
00702 };
00703 
00704 } // namespace SimTK
00705 
00706 #endif // SimTK_SimTKCOMMON_ENUMERATION_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines