diff options
Diffstat (limited to 'src/propertySet.hpp')
-rw-r--r-- | src/propertySet.hpp | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/src/propertySet.hpp b/src/propertySet.hpp new file mode 100644 index 00000000..eb0ee7d7 --- /dev/null +++ b/src/propertySet.hpp @@ -0,0 +1,340 @@ +// +// VMime library (http://vmime.sourceforge.net) +// Copyright (C) 2002-2004 Vincent Richard <[email protected]> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#ifndef VMIME_PROPERTY_HPP_INCLUDED +#define VMIME_PROPERTY_HPP_INCLUDED + + +#include <list> +#include <functional> +#include <algorithm> +#include <sstream> + +#include "base.hpp" +#include "exception.hpp" + + +namespace vmime +{ + + +class propertySet +{ +private: + + class property + { + public: + + property(const string& name, const string& value) : m_name(name), m_value(value) { } + property(const string& name) : m_name(name) { } + property(const property& prop) : m_name(prop.m_name), m_value(prop.m_value) { } + + const string& name() const { return (m_name); } + const string& value() const { return (m_value); } + + template <class TYPE> void set(const TYPE& value); + template <class TYPE> const TYPE get() const; + + private: + + string m_name; + string m_value; + }; + + + class propertyProxy + { + public: + + propertyProxy(const string& name, propertySet* set) + : m_name(name), m_set(set) + { + } + + template <class TYPE> + propertyProxy& operator=(const TYPE& value) + { + m_set->set(m_name, value); + return (*this); + } + + template <class TYPE> + void set(const TYPE& value) + { + m_set->set(m_name, value); + } + + template <class TYPE> + const TYPE get() const + { + return (m_set->get <TYPE>(m_name)); + } + + operator string() const + { + return (m_set->get <string>(m_name)); + } + + private: + + const string m_name; + propertySet* m_set; + }; + + class constPropertyProxy + { + public: + + constPropertyProxy(const string& name, const propertySet* set) + : m_name(name), m_set(set) + { + } + + template <class TYPE> + const TYPE get() const + { + return (m_set->get <TYPE>(m_name)); + } + + operator string() const + { + return (m_set->get <string>(m_name)); + } + + private: + + const string m_name; + const propertySet* m_set; + }; + +public: + + propertySet(); + propertySet(const string& props); + propertySet(const propertySet& set); + + ~propertySet(); + + propertySet& operator=(const propertySet& set); + + void set(const string& props); + + void empty(); + + void clear(const string& name); + + + const bool exists(const string& name) const + { + return (find(name) != NULL); + } + + template <class TYPE> + const TYPE get(const string& name) const + { + const property* const prop = find(name); + if (!prop) throw exceptions::no_such_property(name); + + return (prop->get <TYPE>()); + } + + template <class TYPE> + const TYPE get(const string& name, const TYPE defaultValue) const + { + const property* const prop = find(name); + return (prop ? prop->get <TYPE>() : defaultValue); + } + + template <class TYPE> + void set(const string& name, const TYPE& value) + { + findOrCreate(name)->set(value); + } + + propertyProxy operator[](const string& name) + { + return (propertyProxy(name, this)); + } + + const constPropertyProxy operator[](const string& name) const + { + return (constPropertyProxy(name, this)); + } + +private: + + void parse(const string& props); + + + class propFinder : public std::unary_function <property*, bool> + { + public: + + propFinder(const string& name) : m_name(toLower(name)) { } + + const bool operator()(property* const p) const + { + return (toLower(p->name()) == m_name); + } + + private: + + const std::string m_name; + }; + + property* find(const string& name) const + { + std::list <property*>::const_iterator it = std::find_if + (m_props.begin(), m_props.end(), propFinder(name)); + + return (it != m_props.end() ? *it : NULL); + } + + property* findOrCreate(const string& name) + { + std::list <property*>::const_iterator it = std::find_if + (m_props.begin(), m_props.end(), propFinder(name)); + + if (it != m_props.end()) + { + return (*it); + } + else + { + property* prop = new property(name, ""); + m_props.push_back(prop); + return (prop); + } + } + + typedef std::list <property*> list_type; + list_type m_props; + +public: + + class iterator; + + class const_iterator + { + friend class propertySet; + + public: + + const_iterator() { } + const_iterator(const const_iterator& it) : m_it(it.m_it) { } + const_iterator(const iterator& it) : m_it(it.m_it) { } + + const_iterator& operator=(const const_iterator& it) { m_it = it.m_it; return (*this); } + + const property& operator*() const { return (**m_it); } + const property* operator->() const { return (*m_it); } + + const_iterator& operator++() { ++m_it; return (*this); } + const_iterator operator++(int) { return (m_it++); } + + const_iterator& operator--() { --m_it; return (*this); } + const_iterator operator--(int) { return (m_it--); } + + const bool operator==(const const_iterator& it) const { return (m_it == it.m_it); } + const bool operator!=(const const_iterator& it) const { return (m_it != it.m_it); } + + private: + + const_iterator(const list_type::const_iterator it) : m_it(it) { } + + list_type::const_iterator m_it; + }; + + class iterator + { + friend class propertySet; + friend class propertySet::const_iterator; + + public: + + iterator() { } + iterator(const iterator& it) : m_it(it.m_it) { } + + iterator& operator=(const iterator& it) { m_it = it.m_it; return (*this); } + + property& operator*() const { return (**m_it); } + property* operator->() const { return (*m_it); } + + iterator& operator++() { ++m_it; return (*this); } + iterator operator++(int) { return (m_it++); } + + iterator& operator--() { --m_it; return (*this); } + iterator operator--(int) { return (m_it--); } + + const bool operator==(const iterator& it) const { return (m_it == it.m_it); } + const bool operator!=(const iterator& it) const { return (m_it != it.m_it); } + + private: + + iterator(const list_type::iterator it) : m_it(it) { } + + list_type::iterator m_it; + }; + + iterator begin() { return iterator(m_props.begin()); } + iterator end() { return iterator(m_props.end()); } + + const_iterator begin() const { return const_iterator(m_props.begin()); } + const_iterator end() const { return const_iterator(m_props.end()); } +}; + + + +template <class TYPE> +void propertySet::property::set(const TYPE& value) +{ + std::ostringstream oss; + oss << value; + + m_value = oss.str(); +} + + +template <class TYPE> +const TYPE propertySet::property::get() const +{ + TYPE val = TYPE(); + + std::istringstream iss(m_value); + iss >> val; + + if (iss.fail()) + throw exceptions::invalid_property_type(); + + return (val); +} + + +template <> void propertySet::property::set(const string& value); +template <> void propertySet::property::set(const bool& value); + +template <> const string propertySet::property::get() const; +template <> const bool propertySet::property::get() const; + + +} // vmime + + +#endif // VMIME_PROPERTY_HPP_INCLUDED |