/** * @file generic_spec.h * Container holding an item or a special "match all" item * * @remark Copyright 2003 OProfile authors * @remark Read the file COPYING * * @author John Levon * @author Philippe Elie */ #ifndef GENERIC_SPEC_H #define GENERIC_SPEC_H #include <stdexcept> #include <string> #include <sstream> #include "string_manip.h" /** * used to hold something like { int cpu_nr, bool is_all }; * to store a sub part of a samples filename see PP:3.21. */ template <class T> class generic_spec { public: /** * build a default spec which match anything */ generic_spec(); /// build a spec from a string, valid argument are "all" /// or a string convertible to T through istringtream(str) >> data /// conversion is strict, no space are allowed at begin or end of str void set(std::string const &); /// return true if a specific value is held by this container bool is_set() const { return !is_all; } /// return the specific value (only if is_set() == true) T const value() const { if (!is_all) return data; throw std::out_of_range("generic_spec holds no value"); } /// return true if rhs match this spec. Sub part of PP:3.24 bool match(T const & rhs) const { return rhs == data; } /// return true if rhs match this spec. Sub part of PP:3.24 bool match(generic_spec<T> const & rhs) const { return is_all || rhs.is_all || rhs.data == data; } private: T data; bool is_all; }; template <class T> generic_spec<T>::generic_spec() : data(T()), is_all(true) { } template <class T> void generic_spec<T>::set(std::string const & str) { if (str == "all") { is_all = true; return; } is_all = false; data = op_lexical_cast<T>(str); } /// We don't use generic_spec<string>, since it's probably an error to try /// to use generic_spec<string> we specialize but don't define it to get a /// link error (using generic_spec<string> is problematic because g.set("all") /// is ambiguous) template <> void generic_spec<std::string>::set(std::string const & str); #endif /* !GENERIC_SPEC_H */