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 (int)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_