Simbody
|
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_