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 22 using namespace std; 23 24 cverb_object cverb; 25 verbose vlevel1("level1"); 26 verbose vdebug("debug"); 27 verbose vstats("stats"); 28 verbose vsfile("sfile"); 29 verbose vxml("xml"); 30 31 namespace { 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. 35 ofstream fout("/dev/null"); 36 ostream 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. 40 struct setup_stream { 41 setup_stream(); 42 }; 43 44 setup_stream::setup_stream() 45 { 46 null_stream.clear(ios::badbit); 47 } 48 49 setup_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. 54 typedef multimap<string, verbose *> recorder_t; 55 // The recorder is lazilly created by verbose object ctor 56 static recorder_t * object_map; 57 58 } // anonymous namespace 59 60 61 verbose::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 76 verbose verbose::operator|(verbose const & rhs) 77 { 78 verbose result(*this); 79 result.set = result.set || rhs.set; 80 return result; 81 } 82 83 84 verbose verbose::operator&(verbose const & rhs) 85 { 86 verbose result(*this); 87 result.set = result.set && rhs.set; 88 return result; 89 } 90 91 92 bool 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 111 bool 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 120 ostream& operator<<(cverb_object &, verbose const & v) 121 { 122 return v.set ? cout : null_stream; 123 } 124