Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

Enum.h

Go to the documentation of this file.
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.

[SF.net]