Home | History | Annotate | Download | only in libutil++
      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