cverb.cpp revision 8cfa702f803c5ef6a2b062a489a1b2cf66b45b5e
1/**
2 * @file cverb.cpp
3 * verbose output stream
4 *
5 * @remark Copyright 2002, 2004  OProfile authors
6 * @remark Read the file COPYING
7 *
8 * @author Philippe Elie
9 * @author John Levon
10 */
11
12#include <cstring>
13
14#include <fstream>
15#include <iostream>
16#include <map>
17#include <string>
18#include <cstring>
19
20#include "cverb.h"
21
22using namespace std;
23
24cverb_object cverb;
25verbose vlevel1("level1");
26verbose vdebug("debug");
27verbose vstats("stats");
28verbose vsfile("sfile");
29verbose vxml("xml");
30
31namespace {
32
33// The right way is to use: ofstream fout; but cverb(fout.rdbuf()) receive
34// a null pointer and stl shipped with 2.91 segfault.
35ofstream fout("/dev/null");
36ostream null_stream(fout.rdbuf());
37
38// Used to setup the bad bit in our null stream so output will fail earlier
39// and overhead will be smaller.
40struct setup_stream {
41	setup_stream();
42};
43
44setup_stream::setup_stream()
45{
46	null_stream.clear(ios::badbit);
47}
48
49setup_stream setup;
50
51// We use a multimap because user can create multiple verbose object with
52// the same name, these are synonymous, setting up one to true will setup
53// all with the same name to true.
54typedef multimap<string, verbose *> recorder_t;
55// The recorder is lazilly created by verbose object ctor
56static recorder_t * object_map;
57
58} // anonymous namespace
59
60
61verbose::verbose(char const * name)
62	:
63	set(false)
64{
65	// all params is treated a part, there is no need to create a
66	// verbose all("all"); it's meaningless. "all" verbose named object is
67	// reserved.
68	if (strcmp(name, "all") == 0)
69		return;
70	if (!object_map)
71		object_map = new recorder_t;
72	object_map->insert(recorder_t::value_type(name, this));
73}
74
75
76verbose verbose::operator|(verbose const & rhs)
77{
78	verbose result(*this);
79	result.set = result.set || rhs.set;
80	return result;
81}
82
83
84verbose verbose::operator&(verbose const & rhs)
85{
86	verbose result(*this);
87	result.set = result.set && rhs.set;
88	return result;
89}
90
91
92bool verbose::setup(string const & name)
93{
94	if (name == "all") {
95		null_stream.rdbuf(cout.rdbuf());
96		null_stream.clear();
97		return true;
98	}
99	if (!object_map)
100		object_map = new recorder_t;
101	pair<recorder_t::iterator, recorder_t::iterator> p_it =
102		object_map->equal_range(name);
103	if (p_it.first == p_it.second)
104		return false;
105	for (; p_it.first != p_it.second; ++p_it.first)
106		p_it.first->second->set = true;
107	return true;
108}
109
110
111bool verbose::setup(vector<string> const & names)
112{
113	for (size_t i = 0; i < names.size(); ++i)
114		if (!setup(names[i]))
115			return false;
116	return true;
117}
118
119
120ostream& operator<<(cverb_object &, verbose const & v)
121{
122	return v.set ? cout : null_stream;
123}
124