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