00001 /* SimData: Data Infrastructure for Simulations 00002 * Copyright (C) 2002, 2003 Mark Rose <tm2@stm.lbl.gov> 00003 * 00004 * This file is part of SimData. 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00019 */ 00020 00074 #ifndef __SIMDATA_ENUM_H__ 00075 #define __SIMDATA_ENUM_H__ 00076 00077 #include <SimData/Namespace.h> 00078 #include <SimData/BaseType.h> 00079 #include <SimData/Ref.h> 00080 #include <SimData/Exception.h> 00081 00082 #include <string> 00083 #include <vector> 00084 #include <map> 00085 #include <cstdio> 00086 #include <iostream> 00087 #include <sstream> 00088 00089 00090 00091 NAMESPACE_SIMDATA 00092 00093 00094 class EnumLink; 00095 class Enumeration; 00096 00097 00101 SIMDATA_EXCEPTION(EnumError); 00102 00106 SIMDATA_SUBEXCEPTION(EnumIndexError, EnumError); 00107 00111 SIMDATA_SUBEXCEPTION(EnumTypeError, EnumError); 00112 00113 00114 00126 class EnumerationCore: public Referenced { 00127 friend class Enumeration; 00128 typedef std::pair<std::string, int> Element; 00129 typedef std::vector<Element> Elements; 00130 00132 std::map<int, int> __i2idx; 00133 00135 std::map<std::string, int> __s2idx; 00136 00138 Elements __elements; 00139 00143 void __init(std::string const &s) { 00144 std::stringstream ss(s); 00145 std::string token; 00146 int value = 0; 00147 for (int idx = 0; ss >> token; idx++) { 00148 std::size_t eq = token.find("="); 00149 if (eq != std::string::npos) { 00150 value = atoi(std::string(token, eq+1, std::string::npos).c_str()); 00151 token = std::string(token, 0, eq); 00152 } 00153 if (__i2idx.find(value) != __i2idx.end()) { 00154 std::stringstream msg; 00155 msg << "Enumeration value '" << value << "' multiply defined in '" << s << "'"; 00156 throw EnumError(msg.str()); 00157 } 00158 if (__s2idx.find(token) != __s2idx.end()) { 00159 std::stringstream msg; 00160 msg << "Enumeration token '" << token << "' multiply defined in '" << s << "'"; 00161 throw EnumError(msg.str()); 00162 } 00163 __elements.push_back(Element(token, value)); 00164 __i2idx[value] = idx; 00165 __s2idx[token] = idx; 00166 value++; 00167 } 00168 if (__elements.size() <= 0) throw EnumError("Empty Enumeration"); 00169 } 00170 00172 Element const &getElementByIndex(int idx) const { 00173 assert(validIndex(idx)); 00174 return __elements[idx]; 00175 } 00176 00178 std::string getTokenByIndex(int idx) const { return getElementByIndex(idx).first; } 00179 00181 int getValueByIndex(int idx) const { return getElementByIndex(idx).second; } 00182 00186 int getIndexByValue(int value) const { 00187 std::map<int, int>::const_iterator iter = __i2idx.find(value); 00188 if (iter == __i2idx.end()) { 00189 std::stringstream msg; 00190 msg << value; 00191 throw EnumIndexError(msg.str()); 00192 } 00193 return iter->second; 00194 } 00195 00197 std::string getTokenByValue(int value) const { 00198 return __elements[getIndexByValue(value)].first; 00199 } 00200 00204 int getIndexByToken(std::string const &token) const { 00205 std::map<std::string, int>::const_iterator iter = __s2idx.find(token); 00206 if (iter == __s2idx.end()) { 00207 throw EnumIndexError(token); 00208 } 00209 return iter->second; 00210 } 00211 00213 int getValueByToken(std::string const &token) const { 00214 return __elements[getIndexByToken(token)].second; 00215 } 00216 00218 int size() const { return __elements.size(); } 00219 00221 bool containsToken(std::string const &token) const { 00222 return __s2idx.find(token) != __s2idx.end(); 00223 } 00224 00226 bool containsValue(int value) const { 00227 return __i2idx.find(value) != __i2idx.end(); 00228 } 00229 00231 bool validIndex(int idx) const { 00232 return idx >= 0 && idx <= size(); 00233 } 00234 00238 EnumerationCore(); 00239 00255 EnumerationCore(std::string const &s): Referenced() { 00256 __init(s); 00257 } 00258 }; 00259 00286 class Enumeration { 00287 friend class EnumLink; 00289 Ref<EnumerationCore const> __core; 00290 00292 Enumeration() { } 00293 00295 Enumeration(Enumeration const &e) { 00296 __core = e.__core; 00297 assert(__core.valid()); 00298 } 00299 00301 bool operator !() const { return !__core; } 00302 00304 bool valid() const { return __core.valid(); } 00305 00307 Enumeration const &operator =(Enumeration const &e) { 00308 __core = e.__core; 00309 assert(__core.valid()); 00310 return *this; 00311 } 00312 00314 int getIndexByToken(std::string const &token) const { 00315 assert(__core.valid()); 00316 return __core->getIndexByToken(token); 00317 } 00318 00320 int getIndexByValue(int value) const { 00321 assert(__core.valid()); 00322 return __core->getIndexByValue(value); 00323 } 00324 00326 std::string getTokenByIndex(int idx) const { 00327 assert(__core.valid()); 00328 return __core->getTokenByIndex(idx); 00329 } 00330 00332 int getValueByIndex(int idx) const { 00333 assert(__core.valid()); 00334 return __core->getValueByIndex(idx); 00335 } 00336 00341 inline const std::vector<EnumLink> __range(int idx1, int idx2) const; 00342 00343 void __checkIndex(int idx) const { 00344 assert(__core.valid() && __core->validIndex(idx)); 00345 } 00346 00348 inline EnumLink makeEnum(int idx) const; 00349 00350 public: 00352 bool operator ==(Enumeration const &e) const { return __core == e.__core; } 00353 00355 bool operator !=(Enumeration const &e) const { return __core != e.__core; } 00356 00371 Enumeration(std::string const &s) { 00372 __core = new EnumerationCore(s); 00373 } 00374 00376 std::string getToken(int value) const { 00377 assert(__core.valid()); 00378 return __core->getTokenByValue(value); 00379 } 00380 00382 int getValue(std::string const &token) const { 00383 assert(__core.valid()); 00384 return __core->getValueByToken(token); 00385 } 00386 00388 int size() const{ 00389 assert(__core.valid()); 00390 return __core->size(); 00391 } 00392 00394 std::string __repr__() const { 00395 assert(__core.valid()); 00396 std::stringstream ss; 00397 ss << "<Enumeration:"; 00398 for (int i = 0; i < size(); i++) { 00399 ss << " " << __core->getTokenByIndex(i) 00400 << "=" << __core->getValueByIndex(i); 00401 } 00402 ss << ">"; 00403 return ss.str(); 00404 } 00405 00407 inline const std::vector<EnumLink> each() const; 00408 00410 inline const std::vector<std::string> eachToken() const; 00411 00413 inline const std::vector<int> eachValue() const; 00414 00416 inline const std::vector<EnumLink> range(EnumLink const &a, EnumLink const &b) const; 00417 00419 inline const std::vector<EnumLink> range(std::string const &a, std::string const &b) const; 00420 00422 inline const std::vector<EnumLink> range(int a, int b) const; 00423 00425 inline bool contains(EnumLink const &x) const; 00426 00428 bool contains(int value) const { 00429 assert(__core.valid()); 00430 return __core->containsValue(value); 00431 } 00432 00434 bool contains(std::string const &token) const { 00435 assert(__core.valid()); 00436 return __core->containsToken(token); 00437 } 00438 00440 inline EnumLink last() const; 00441 00443 inline EnumLink first() const; 00444 00445 #ifndef SWIG 00446 00447 inline EnumLink operator[](int value) const; 00449 inline EnumLink operator[](std::string const &token) const; 00450 #else 00451 %extend { 00453 EnumLink get(int idx) { return (*self)[idx]; } 00455 EnumLink get(std::string const &s) { return (*self)[s]; } 00456 } 00460 %insert(shadow) %{ 00461 def __getitem__(self, idx): 00462 return self.get(idx) 00463 def __getattr__(self, attr): 00464 if self.contains(attr): 00465 return self.get(attr) 00466 return self.__dict__[attr] 00467 %} 00468 #endif 00469 }; 00470 00471 00472 00484 class EnumLink: public BaseType { 00485 friend class Enumeration; 00487 Enumeration __E; 00488 protected: 00490 int _idx; 00491 00493 int __size() const { return __E.size(); } 00494 00496 EnumLink(): __E(), _idx(0) {} 00497 00499 int getIndex() const { return _idx; } 00500 00502 EnumLink(int idx, Enumeration const &E): __E(E), _idx(idx) { 00503 E.__checkIndex(idx); 00504 } 00505 00507 EnumLink makeEnum(int idx) const { 00508 return EnumLink(idx, __E); 00509 } 00510 00511 public: 00512 // Create a new EnumLink bound to an existing Enumeration. 00513 EnumLink(Enumeration const &E): __E(E), _idx(0) { } 00514 00515 // Create a new EnumLink bound to an existing Enumeration. 00516 EnumLink(Enumeration const &E, int value): __E(E), _idx(0) { 00517 _idx = __E.getIndexByValue(value); 00518 } 00519 00520 // Create a new EnumLink bound to an existing Enumeration. 00521 EnumLink(Enumeration const &E, std::string const &token): __E(E), _idx(0) { 00522 _idx = __E.getIndexByToken(token); 00523 } 00524 00526 virtual void serialize(Archive&); 00527 00529 virtual void parseXML(const char* cdata); 00530 00532 virtual std::string typeString() const; 00533 00535 virtual std::string asString() const; 00536 00538 EnumLink(EnumLink const &e): BaseType() { 00539 __E = e.__E; 00540 _idx = e._idx; 00541 } 00542 00544 void cycle(int n=1) { _idx = (_idx+n+abs(n)*__size()) % __size(); } 00545 00547 void cycleBack(int n=1) { _idx = (_idx-n+abs(n)*__size()) % __size(); } 00548 00550 void set(std::string const &token) { _idx = __E.getIndexByToken(token); } 00551 00553 void set(int value) { _idx = __E.getIndexByValue(value); } 00554 00556 int getValue() const { return __E.getValueByIndex(_idx); } 00557 00558 // Get the token of this enum. 00559 std::string getToken() const { return __E.getTokenByIndex(_idx); } 00560 00562 std::string __repr__() const { 00563 std::stringstream repr; 00564 repr << "<Enum:" << getToken() << "=" << getValue() << ">"; 00565 return repr.str(); 00566 } 00567 00569 EnumLink next(int n=1) const { return makeEnum((_idx+n+abs(n)*__size())%__size()); } 00570 00572 EnumLink prev(int n=1) const { return makeEnum((_idx-n+abs(n)*__size())%__size()); } 00573 00575 EnumLink last() const { return makeEnum(__size()-1); } 00576 00578 EnumLink first() const { return makeEnum(0); } 00579 00581 Enumeration const &getEnumeration() const { return __E; } 00582 00583 #ifndef SWIG 00584 00585 operator int() const { return getValue(); } 00586 00588 operator std::string() const { return getToken(); } 00589 00591 EnumLink const &operator =(int value) { set(value); return *this; } 00592 00594 EnumLink const &operator =(std::string const &token) { set(token); return *this; } 00595 00597 EnumLink const &operator=(EnumLink const &e) { 00598 if (!__E) { 00599 __E = e.__E; 00600 } else { 00601 if (__E != e.__E) throw EnumTypeError(); 00602 } 00603 if (__E.valid()) { _idx = e._idx; } 00604 return *this; 00605 } 00606 #endif 00607 00609 bool operator>(std::string const &token) const { return getValue() > __E.getValue(token); } 00610 00612 bool operator<(std::string const &token) const { return getValue() < __E.getValue(token); } 00613 00615 bool operator>=(std::string const &token) const { return getValue() >= __E.getValue(token); } 00616 00618 bool operator<=(std::string const &token) const { return getValue() <= __E.getValue(token); } 00619 00621 bool operator==(std::string const &token) const { return getValue() == __E.getValue(token); } 00622 00624 bool operator!=(std::string const &token) const { return getValue() != __E.getValue(token); } 00625 00627 bool operator>(int value) const { return getValue() > value; } 00628 00630 bool operator<(int value) const { return getValue() < value; }; 00631 00633 bool operator>=(int value) const { return getValue() >= value; }; 00634 00636 bool operator<=(int value) const { return getValue() <= value; }; 00637 00639 bool operator==(int value) const { return getValue() == value; }; 00640 00642 bool operator!=(int value) const { return getValue() != value; }; 00643 00645 bool operator>(EnumLink const &x) const { return *this > x.getValue(); } 00646 00648 bool operator<(EnumLink const &x) const { return *this < x.getValue(); } 00649 00651 bool operator>=(EnumLink const &x) const { return *this >= x.getValue(); } 00652 00654 bool operator<=(EnumLink const &x) const { return *this <= x.getValue(); } 00655 00657 bool operator==(EnumLink const &x) const { return *this == x.getValue(); } 00658 00660 bool operator!=(EnumLink const &x) const { return *this != x.getValue(); } 00661 }; 00662 00677 template <Enumeration const &E> 00678 class Enum: public EnumLink { 00679 public: 00680 Enum(std::string const &token): EnumLink(E, token) {} 00681 Enum(): EnumLink(E) {} 00682 Enum(int value): EnumLink(E, value) {} 00683 Enum(EnumLink const &e): EnumLink(e) {} 00684 #ifndef SWIG 00685 EnumLink const & operator=(EnumLink const &e) { return EnumLink::operator=(e); } 00686 EnumLink const &operator =(int value) { return EnumLink::operator=(value); } 00687 EnumLink const &operator =(std::string const &token) { return EnumLink::operator=(token); } 00688 #endif 00689 00690 std::string __repr__() const { return EnumLink::__repr__(); } 00691 }; 00692 00693 00694 // inline Enumeration methods 00695 00696 inline EnumLink Enumeration::makeEnum(int idx) const { return EnumLink(idx, *this); } 00697 00698 inline EnumLink Enumeration::operator[](int value) const { return makeEnum(getIndexByValue(value)); } 00699 00700 inline EnumLink Enumeration::operator[](std::string const &token) const { return makeEnum(getIndexByToken(token)); } 00701 00702 inline const std::vector<EnumLink> Enumeration::__range(int idx1, int idx2) const { 00703 assert(__core.valid()); 00704 std::vector<EnumLink> v; 00705 if (idx2 >= idx1) { 00706 v.reserve(idx2-idx1+1); 00707 } 00708 for (int idx = idx1; idx <= idx2; idx++) { 00709 v.push_back(makeEnum(idx)); 00710 } 00711 return v; 00712 } 00713 00714 inline const std::vector<EnumLink> Enumeration::range(EnumLink const &a, EnumLink const &b) const { 00715 if (a.__E != *this || b.__E != *this) throw EnumTypeError(); 00716 return __range(a.getIndex(), b.getIndex()); 00717 } 00718 00719 inline const std::vector<EnumLink> Enumeration::range(std::string const &a, std::string const &b) const { 00720 return __range(getIndexByToken(a), getIndexByToken(b)); 00721 } 00722 00723 inline const std::vector<EnumLink> Enumeration::range(int a, int b) const { 00724 return __range(getIndexByValue(a), getIndexByValue(b)); 00725 } 00726 00727 inline const std::vector<EnumLink> Enumeration::each() const { 00728 std::vector<EnumLink> v; 00729 v.reserve(size()); 00730 for (int idx = 0; idx < size(); idx++) { 00731 v.push_back(makeEnum(idx)); 00732 } 00733 return v; 00734 } 00735 00736 inline const std::vector<std::string> Enumeration::eachToken() const { 00737 assert(__core.valid()); 00738 std::vector<std::string> v; 00739 v.reserve(size()); 00740 for (int idx = 0; idx < size(); idx++) { 00741 v.push_back(__core->getTokenByIndex(idx)); 00742 } 00743 return v; 00744 } 00745 00746 inline const std::vector<int> Enumeration::eachValue() const { 00747 assert(__core.valid()); 00748 std::vector<int> v; 00749 v.reserve(size()); 00750 for (int idx = 0; idx < size(); idx++) { 00751 v.push_back(__core->getValueByIndex(idx)); 00752 } 00753 return v; 00754 } 00755 00756 inline bool Enumeration::contains(EnumLink const &x) const { return x.__E == *this; } 00757 00758 inline EnumLink Enumeration::last() const { 00759 assert(__core.valid()); 00760 return makeEnum(size()-1); 00761 } 00762 00763 inline EnumLink Enumeration::first() const { 00764 assert(__core.valid()); 00765 return makeEnum(0); 00766 } 00767 00768 00769 NAMESPACE_SIMDATA_END 00770 00771 #endif // __SIMDATA_ENUM_H__ 00772
|
SimData version pre-0.4.0. For more information on SimData, visit the SimData Homepage. Generated on Tue Oct 14 12:06:38 2003, using Doxygen 1.2.18. |