1/**
2 * @file generic_spec.h
3 * Container holding an item or a special "match all" item
4 *
5 * @remark Copyright 2003 OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author John Levon
9 * @author Philippe Elie
10 */
11
12#ifndef GENERIC_SPEC_H
13#define GENERIC_SPEC_H
14
15#include <stdexcept>
16#include <string>
17#include <sstream>
18
19#include "string_manip.h"
20
21
22/**
23 * used to hold something like { int cpu_nr, bool is_all };
24 * to store a sub part of a samples filename see PP:3.21.
25 */
26template <class T>
27class generic_spec
28{
29public:
30	/**
31	 * build a default spec which match anything
32	 */
33	generic_spec();
34
35	/// build a spec from a string, valid argument are "all"
36	/// or a string convertible to T through istringtream(str) >> data
37	/// conversion is strict, no space are allowed at begin or end of str
38	void set(std::string const &);
39
40	/// return true if a specific value is held by this container
41	bool is_set() const {
42		return !is_all;
43	}
44
45	/// return the specific value (only if is_set() == true)
46	T const value() const {
47		if (!is_all)
48			return data;
49		throw std::out_of_range("generic_spec holds no value");
50	}
51
52	/// return true if rhs match this spec. Sub part of PP:3.24
53	bool match(T const & rhs) const {
54		return rhs == data;
55	}
56
57	/// return true if rhs match this spec. Sub part of PP:3.24
58	bool match(generic_spec<T> const & rhs) const {
59		return is_all || rhs.is_all || rhs.data == data;
60	}
61
62private:
63	T data;
64	bool is_all;
65};
66
67
68template <class T>
69generic_spec<T>::generic_spec()
70	:
71	data(T()),
72	is_all(true)
73{
74}
75
76
77template <class T>
78void generic_spec<T>::set(std::string const & str)
79{
80	if (str == "all") {
81		is_all = true;
82		return;
83	}
84
85	is_all = false;
86	data = op_lexical_cast<T>(str);
87}
88
89
90/// We don't use generic_spec<string>, since it's probably an error to try
91/// to use generic_spec<string> we specialize but don't define it to get a
92/// link error (using generic_spec<string> is problematic because g.set("all")
93/// is ambiguous)
94template <>
95void generic_spec<std::string>::set(std::string const & str);
96
97#endif /* !GENERIC_SPEC_H */
98