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_