/** * @file cverb.cpp * verbose output stream * * @remark Copyright 2002, 2004 OProfile authors * @remark Read the file COPYING * * @author Philippe Elie * @author John Levon */ #include <cstring> #include <fstream> #include <iostream> #include <map> #include <string> #include <cstring> #include "cverb.h" using namespace std; cverb_object cverb; verbose vlevel1("level1"); verbose vdebug("debug"); verbose vstats("stats"); verbose vsfile("sfile"); verbose vxml("xml"); namespace { // The right way is to use: ofstream fout; but cverb(fout.rdbuf()) receive // a null pointer and stl shipped with 2.91 segfault. ofstream fout("/dev/null"); ostream null_stream(fout.rdbuf()); // Used to setup the bad bit in our null stream so output will fail earlier // and overhead will be smaller. struct setup_stream { setup_stream(); }; setup_stream::setup_stream() { null_stream.clear(ios::badbit); } setup_stream setup; // We use a multimap because user can create multiple verbose object with // the same name, these are synonymous, setting up one to true will setup // all with the same name to true. typedef multimap<string, verbose *> recorder_t; // The recorder is lazilly created by verbose object ctor static recorder_t * object_map; } // anonymous namespace verbose::verbose(char const * name) : set(false) { // all params is treated a part, there is no need to create a // verbose all("all"); it's meaningless. "all" verbose named object is // reserved. if (strcmp(name, "all") == 0) return; if (!object_map) object_map = new recorder_t; object_map->insert(recorder_t::value_type(name, this)); } verbose verbose::operator|(verbose const & rhs) { verbose result(*this); result.set = result.set || rhs.set; return result; } verbose verbose::operator&(verbose const & rhs) { verbose result(*this); result.set = result.set && rhs.set; return result; } bool verbose::setup(string const & name) { if (name == "all") { null_stream.rdbuf(cout.rdbuf()); null_stream.clear(); return true; } if (!object_map) object_map = new recorder_t; pair<recorder_t::iterator, recorder_t::iterator> p_it = object_map->equal_range(name); if (p_it.first == p_it.second) return false; for (; p_it.first != p_it.second; ++p_it.first) p_it.first->second->set = true; return true; } bool verbose::setup(vector<string> const & names) { for (size_t i = 0; i < names.size(); ++i) if (!setup(names[i])) return false; return true; } ostream& operator<<(cverb_object &, verbose const & v) { return v.set ? cout : null_stream; }