00001 #ifndef DV_UTIL_ENV_H
00002 #define DV_UTIL_ENV_H
00003
00004 #include <string>
00005 #include <stdexcept>
00006 #include <iostream>
00007 #include <map>
00008 #include <list>
00009 #include <vector>
00010 #include <iterator>
00011 #include <dvutil/tostring.h>
00012 #include <dvutil/props.h>
00013 #include "noconst.h"
00014
00032 namespace Dv {
00033 namespace Util {
00131 class Env {
00132 public:
00134 class Exception: public std::runtime_error {
00135 public:
00139 static const std::string NAME;
00144 Exception(const std::string& msg): std::runtime_error(NAME + ": " + msg) {}
00145 };
00146
00150 Env();
00155 Env(const Env& e);
00161 Env(std::istream& is) throw (Exception);
00167 Env(const std::string& fn) throw (Exception);
00168
00172 ~Env();
00173
00174 class iterator;
00175
00176
00183 const std::string& svalue() const throw (Exception);
00191 std::string& slvalue() throw (Exception);
00192
00199 template<typename T>
00200 operator T() const throw (Exception) {
00201 typename noconst<T>::mutable_type t;
00202 if (!Dv::Util::fromstring(t,svalue()))
00203 throw Exception(svalue() + ": cannot convert");
00204 return t;
00205 }
00206
00211 template<typename T>
00212 operator T*() const throw (Exception) {
00213 throw Exception(svalue() + ": cannot convert fo T*");
00214 return 0; }
00215
00219 operator const char*() const throw (Exception) {
00220 return svalue().c_str();
00221 }
00222
00230 operator const std::string&() const throw (Exception) { return svalue(); }
00238 operator std::string&() throw (Exception) { return slvalue(); }
00239
00244 bool defined() const { return box_ != 0; }
00245
00249 enum Type { NIL ,
00250 STRING ,
00251 MAP ,
00252 ARRAY
00253 };
00259 Type type() const;
00260
00261 static const char* type_s(Type t);
00262
00267 bool is_string() const { return type() == STRING; }
00272 bool is_array() const { return type() == ARRAY; }
00277 bool is_map() const { return type() == MAP; }
00278
00283 static const Env& nil();
00284
00291 Env& operator[](int i) throw (Exception);
00297 const Env& operator()(int i) const throw (Exception);
00298
00305 Env& operator[](const std::string& s) throw (Exception);
00311 const Env& operator()(const std::string& s) const throw (Exception);
00312
00320 template<typename T>
00321 Env& operator=(const T& t) {
00322 if (this!=&nil())
00323 slvalue() = Dv::Util::tostring(t);
00324 return *this;
00325 }
00326
00334 Env& operator=(const std::string& s);
00335
00343 Env& operator=(const Env& e);
00344
00349 Env& clear() { return *this = nil(); }
00368 Env& merge(const Env& e);
00369
00374 size_t size() const;
00375
00382 template<typename T>
00383 bool
00384 operator==(const T& t) const {
00385 return static_cast<T>(*this) == t;
00386 }
00387
00394 bool
00395 operator==(const std::string& s) const {
00396 return svalue() == s;
00397 }
00398
00405 bool
00406 operator==(const Env& e) const;
00407
00408 template<typename T>
00409 bool
00410 operator!=(const T& t) const {
00411 return ! (*this == t);
00412 }
00413
00453 const Env& substitute(std::ostream& os, std::istream& is) const throw (Exception);
00454
00494 const Env& substitute(std::string& out, const std::string& ins) const throw (Exception);
00495
00496
00508 std::ostream& print(std::ostream& os, const std::string& prefix = "") const;
00509
00512 Env& read_key(const std::string& s) throw (Exception);
00521 static bool explode(const std::string& index, std::vector<std::string>& keys);
00522
00532 class Display {
00533 public:
00538 Display(const Env& e);
00539 Display(const Display& d);
00540 size_t size() const { return envs_.size(); }
00544 const Env* top() const { return envs_.front(); }
00545 Display& push(const std::string& key);
00546 Display& pop();
00547 const Env* operator()(const std::string& key) const;
00548 const Env* operator()(const std::vector<std::string>& keys) const;
00549 Display& expand(const std::vector<std::string>& keys);
00550 void substitute(std::ostream& os, std::istream& is) const throw (Exception);
00551 std::ostream& print(std::ostream& os) const;
00552 private:
00553 std::list<const Env*> envs_;
00554 std::list<std::string> names_;
00555 };
00556
00562 const Env* access(const std::string& key) const;
00569
00570
00580 Env& read(std::istream& is) throw (Dv::Util::Env::Exception);
00581
00582 protected:
00583
00584 class SBox;
00585 class MBox;
00586 class ABox;
00587
00591 class Box {
00592 public:
00596 class iterator {
00597 public:
00598 typedef std::map<std::string,const Env*>::iterator::value_type value_type;
00599 virtual iterator& operator++();
00600 virtual value_type operator*() const;
00601 virtual bool equal(const iterator* i) const;
00602 };
00603
00608 Type type() const;
00609
00615 virtual iterator* begin() const throw (Exception);
00621 virtual iterator* end() const throw (Exception);
00622
00629 operator std::string&() throw (Exception) { return slvalue(); }
00636 operator const std::string&() const throw (Exception) { return svalue(); }
00637
00643 virtual const std::string& svalue() const throw (Exception);
00649 virtual std::string& slvalue() throw (Exception);
00650
00657 virtual Env* operator[](int i) throw (Exception);
00664 virtual const Env* operator()(int i) const throw (Exception);
00665
00672 virtual Env* operator[](const std::string& s) throw (Exception);
00679 virtual const Env* operator()(const std::string& s) const throw (Exception);
00680 virtual ~Box();
00681 };
00682
00683 public:
00687 class iterator {
00688 public:
00689 typedef Box::iterator::value_type value_type;
00690 iterator(Box::iterator* it): it_(it) {}
00691 ~iterator() { delete it_; }
00692 iterator& operator++() { ++*it_; return *this; }
00693 value_type operator*() const;
00694 bool operator==(const iterator& i) const {
00695 return ( it_ == i.it_ ? true : it_->equal(i.it_) ); }
00696 bool operator!=(const iterator& i) const { return ! (*this == i); }
00697 private:
00698 Box::iterator* it_;
00699 };
00700
00701 iterator begin() const;
00702 iterator end() const;
00703
00704 protected:
00705
00707 class SBox: public Box {
00708 public:
00709 virtual const std::string& svalue() const throw (Exception) { return s_; }
00710 virtual std::string& slvalue() throw (Exception) { return s_; }
00711 private:
00712 std::string s_;
00713 };
00714
00716 class MBox: public Box {
00717 public:
00718 typedef std::map<std::string, Env*> Map;
00719
00721 class iterator: public Box::iterator {
00722 public:
00723 iterator(Map::const_iterator it): it_(it) {}
00724 iterator& operator++() { ++it_; return *this; }
00725 value_type operator*() const { return *it_; }
00726 bool equal(const Box::iterator* i) const;
00727 private:
00728 Map::const_iterator it_;
00729 };
00730
00731 iterator* begin() const throw (Exception) { return new iterator(m_.begin()); }
00732 iterator* end() const throw (Exception) { return new iterator(m_.end()); }
00733
00734 MBox();
00735 ~MBox();
00736
00740 size_t size() const { return m_.size(); }
00746 Env* operator[](const std::string& s) throw (Exception);
00752 const Env* operator()(const std::string& s) const throw (Exception);
00753 private:
00754 Map m_;
00755 };
00756
00758 class ABox: public Box {
00759 public:
00760 typedef std::vector<Env*> Vector;
00761
00763 class iterator: public Box::iterator {
00764 public:
00765 iterator(Vector::const_iterator it, const Vector* v);
00766 iterator& operator++() { ++it_; return *this; }
00767 value_type operator*() const;
00768 bool equal(const Box::iterator* i) const;
00769 private:
00770 Vector::const_iterator it_;
00771 const Vector* const v_;
00772 };
00773
00774 iterator* begin() const throw (Exception) { return new iterator(a_.begin(), &a_); }
00775 iterator* end() const throw (Exception) { return new iterator(a_.end(), &a_); }
00776
00781 ABox(size_t size);
00782 ~ABox();
00783 size_t size() const { return a_.size(); }
00784 Env* operator[](int i) throw (Exception);
00785 const Env* operator()(int i) const throw (Exception);
00786 private:
00787 Vector a_;
00788 };
00789
00790
00791 private:
00792 Box* box_;
00793 };
00794
00795 }}
00796
00797 namespace std {
00806 std::ostream&
00807 operator<<(std::ostream& os, const Dv::Util::Env& e);
00818 std::istream&
00819 operator>>(std::istream& is, Dv::Util::Env& e) throw (Dv::Util::Env::Exception);
00820
00821 inline std::ostream&
00822 operator<<(std::ostream& os, const Dv::Util::Env::Display& d) {
00823 return d.print(os);
00824 }
00825 }
00826 #endif