From: Marc D. <ma...@us...> - 2004-12-28 22:36:52
|
Update of /cvsroot/pclasses/pclasses2/include/pclasses/Util In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21640/include/pclasses/Util Added Files: Prefs.h Variant.h Log Message: added Prefs and Variant class to Util module --- NEW FILE: Prefs.h --- #ifndef Pext_Prefs_h #define Pext_Prefs_h #include <Variant.h> #include <pclasses/pexception.h> #include <string> #include <list> namespace P { namespace Ext { class PrefsStore; //! A class for preference management. class Prefs { public: //! Entries consist of a value and a name. class Entry { public: //! Constructs a new Entry. Entry(const std::string& name, const Variant& value) : _name(name), _value(value) {} //! Destructor. virtual ~Entry() {} //! Returns the name of the entry. const std::string name() const { return _name; } //! Sets the name of this entry void setName(const std::string& name) { _name = name; } //! Returns the value of this entry const Variant& value() { return _value; } //! Sets the value of this entry void setValue(const Variant& value) { _value = value; } //! Returns the value as string. virtual const std::string str() const {return _value.str();} private: std::string _name; Variant _value; }; //! Sections have a name and hold subsections and entries class Section { public: //! Constructs a new Section. Section(const std::string& name); //! Destructor. virtual ~Section(); //! Returns the name of this section. const std::string& name() const {return _name;} //! Sets the name of this section void setName(const std::string& name) {_name = name;} //! Removes all entries and subsections void clear(); //! Returns a list of all Entries. const std::list<Entry*>& entries() const { return _entries; } //! Finds an entry by name. Returns 0 if not found. Entry* entry(const std::string& name); //! Needs to be created with new void addEntry(Entry* entry); //! removes all entries with name. void removeEntries(const std::string& name); //! Returns a list of subsections const std::list<Section*>& sections() const {return _sections;} //! Finds section by name. Returns 0 if not found. Section* section(const std::string& name); //! Needs to be created with new. void addSection(Section* section); //! removes all sections with name void removeSections(const std::string& name); private: std::string _name; std::list<Entry*> _entries; std::list<Section*> _sections; }; public: Prefs(PrefsStore* store = 0, const std::string& name = "root"); virtual ~Prefs(); virtual void clear(); virtual void load() throw(P::IOError); virtual void save() throw(P::IOError); Section& root(); const Section& root() const; PrefsStore* store(); const PrefsStore* store() const; void setStore(PrefsStore* store); private: Section _root; PrefsStore* _store; }; class PrefsStore { public: PrefsStore() {} virtual ~PrefsStore() {} virtual void load(Prefs::Section& root) throw(P::IOError) = 0; virtual void update(Prefs::Section& root) throw(P::IOError) = 0; }; } // namespace P } // namesoace Ext #endif --- NEW FILE: Variant.h --- #ifndef P_Ext_Variant_h #define P_Ext_Variant_h #include <string> #include <iostream> #include <sstream> namespace P { namespace Ext { class Variant { public: Variant() throw() {} ~Variant() throw() {} template <typename T> Variant(const T & t ) throw() { operator=(t); } //! Efficiency overload. Variant( const std::string& f) throw() : m_data(f) { } //! See operator=(const char *) for a note about why this exists. Variant( const char* str ) throw() : m_data(str? str : "") { } //! Copies rhs's data to this object. Variant( const Variant& rhs ) throw() : m_data(rhs.m_data) { } //! Copies rhs's data and returns this object. inline Variant& operator=(const Variant& rhs ) throw() { if( &rhs != this ) this->m_data = rhs.m_data; return *this; } //! Sets this object's value and returns this object. template <typename T> inline Variant& operator=(const T& type ) throw() { std::ostringstream os; os << std::fixed << type; this->m_data = os.str(); return *this; } //! This overload exists to keep the compiler/linker //! from generating a new instantiation of this function //! for each differently-lengthed (const char *) //! which is assigned to a lex_t. inline Variant& operator=( const char* rhs ) throw() { this->m_data = rhs ? rhs : ""; return *this; } //! Returns (this-<str() < rhs.str()). inline bool operator<(const Variant& rhs) const { return this->str() < rhs.str(); } //! Returns (this-<str() > rhs.str()). inline bool operator>(const Variant& rhs) const { return this->str() > rhs.str(); } //! Returns (this-<str() < rhs.str()). inline bool operator<=(const Variant& rhs) const { return this->str() <= rhs.str(); } //! Returns (this-<str() > rhs.str()). inline bool operator>=(const Variant& rhs) const { return this->str() >= rhs.str(); } /** lexically casts str() to a Type, returning defVal if the cast fails. When calling this function you may need to use the following syntax to avoid compile errors: Foo foo = variant.template cast_to<Foo>(); (It's weird, i know, and the first time i saw it, finding the solution to took me days. (Thank you, Nicolai Josuttis!)) However, in normal usage you won't need to use this function, as the generic type conversion operator does the exact same thing: NOTE: why not throw an exception? */ template <typename T> T cast_to( const T& defVal = T() ) const throw() { std::istringstream is(this->m_data); if( !is ) return defVal; T retVal = T(); if(is >> retVal) return retVal; return defVal; } /** i used to LOVE C++... After writing this function i WORSHIP C++. The grace with which C++ handles this is pure magic, my friends. 16.8.2004 ----- stephan */ template <typename T> inline operator T() const throw() { return this->template cast_to<T>(); } //!Overload to avoid ambiguity in some cases. inline operator std::string() const throw() { return this->str(); } //! Returns the same as str(). operator std::string&() throw() { return this->m_data; } //! Returns the same as str(). operator const std::string&() const throw() { return this->m_data; } //! Overload to avoid ambiguity in some cases. //! Useful for mixing C and C++ APIs: inline operator const char*() const throw() { return this->str().c_str(); } //! Returns a reference to this object's raw string data. inline std::string & str() throw() { return this->m_data; } //! Returns a const reference to this object's raw string data. inline const std::string & str() const throw() { return this->m_data; } //! Returns true if this object contains no data, else false. inline bool empty() const { return this->m_data.empty(); } private: std::string m_data; }; //! Copies a.str() to std::ostream. inline std::ostream& operator<<(std::ostream& os, const Variant& v ) { return os << v.str(); } /** Reads from the input stream, appending to a.str() until the stream gives up. If the implementation of this function seems "wrong" to you, please read the justification in this paper: http://s11n.net/papers/lexically_casting.html NOTE: Url doesnt exist. Are we keeping this? */ inline std::istream & operator>>(std::istream& is, Variant& v) { char c; // while( std::getline( is, v.str() ).good() ); // ^^^ eeek! strips newlines! while( ! is.get(c).eof() ) { v.str().append( &c ); } return is; } /** Casts lhs to a T object and returns true only if that object compares as equal to rhs. NOTE: Is there an advantage not to have this operator in Variant? */ template <typename T> inline bool operator==(const Variant& lhs, const T& rhs ) { return lhs.template cast_to<T>() == rhs; } //! Returns lhs.str() == rhs.str(). inline bool operator==( const Variant& lhs, const Variant& rhs ) { return lhs.str() == rhs.str(); } /** Avoid an ambiguity... If rhs == 0 then this function returns true if lhs.empty(). */ inline bool operator==( const Variant& lhs, const char* rhs ) { if( ! rhs ) return lhs.empty(); return lhs.str() == std::string(rhs); } //! Avoid an ambiguity... inline bool operator==( const Variant& lhs, const std::string& rhs ) { return lhs.str() == rhs; } } } #include <Variant.tpp> #endif |