/**
 * @file format_output.cpp
 * outputting format for symbol lists
 *
 * @remark Copyright 2002 OProfile authors
 * @remark Read the file COPYING
 *
 * @author Philippe Elie
 * @author John Levon
 */

/* older glibc has C99 INFINITY in _GNU_SOURCE */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <sstream>
#include <iomanip>
#include <iostream>
#include <cmath>

#include "string_manip.h"

#include "format_output.h"
#include "profile_container.h"
#include "callgraph_container.h"
#include "diff_container.h"

using namespace std;


namespace {

string const & get_image_name(image_name_id id, bool lf)
{
	return lf ? image_names.name(id) : image_names.basename(id);
}

string const get_linenr_info(file_location const floc, bool lf)
{
	ostringstream out;

	string const & filename = lf
		? debug_names.name(floc.filename)
		: debug_names.basename(floc.filename);

	if (!filename.empty()) {
		out << filename << ":" << floc.linenr;
	} else {
		out << "(no location information)";
	}

	return out.str();
}

string get_vma(bfd_vma vma, bool vma_64)
{
	ostringstream out;
	int width = vma_64 ? 16 : 8;

	out << hex << setw(width) << setfill('0') << vma;

	return out.str();
}

string get_percent(size_t dividend, size_t divisor)
{
	double ratio = op_ratio(dividend, divisor);

	return ::format_percent(ratio * 100, percent_int_width,
	                     percent_fract_width);
}

} // anonymous namespace


namespace format_output {


formatter::formatter()
	:
	nr_classes(1),
	flags(ff_none),
	vma_64(false),
	long_filenames(false),
	need_header(true)
{
	format_map[ff_vma] = field_description(9, "vma", &formatter::format_vma);
	format_map[ff_nr_samples] = field_description(9, "samples", &formatter::format_nr_samples);
	format_map[ff_nr_samples_cumulated] = field_description(14, "cum. samples", &formatter::format_nr_cumulated_samples);
	format_map[ff_percent] = field_description(9, "%", &formatter::format_percent);
	format_map[ff_percent_cumulated] = field_description(11, "cum. %", &formatter::format_cumulated_percent);
	format_map[ff_linenr_info] = field_description(28, "linenr info", &formatter::format_linenr_info);
	format_map[ff_image_name] = field_description(25, "image name", &formatter::format_image_name);
	format_map[ff_app_name] = field_description(25, "app name", &formatter::format_app_name);
	format_map[ff_symb_name] = field_description(30, "symbol name", &formatter::format_symb_name);
	format_map[ff_percent_details] = field_description(9, "%", &formatter::format_percent_details);
	format_map[ff_percent_cumulated_details] = field_description(10, "cum. %", &formatter::format_cumulated_percent_details);
	format_map[ff_diff] = field_description(10, "diff %", &formatter::format_diff);
}


formatter::~formatter()
{
}


void formatter::set_nr_classes(size_t nr)
{
	nr_classes = nr;
}


void formatter::add_format(format_flags flag)
{
	flags = static_cast<format_flags>(flags | flag);
}


void formatter::show_header(bool on_off)
{
	need_header = on_off;
}
 

void formatter::vma_format_64bit(bool on_off)
{
	vma_64 = on_off;
}


void formatter::show_long_filenames(bool on_off)
{
	long_filenames = on_off;
}


void formatter::show_global_percent(bool on_off)
{
	global_percent = on_off;
}


void formatter::output_header(ostream & out)
{
	if (!need_header)
		return;

	size_t padding = 0;

	// first output the vma field
	if (flags & ff_vma)
		padding = output_header_field(out, ff_vma, padding);

	// the field repeated for each profile class
	for (size_t pclass = 0 ; pclass < nr_classes; ++pclass) {
		if (flags & ff_nr_samples)
			padding = output_header_field(out,
			      ff_nr_samples, padding);

		if (flags & ff_nr_samples_cumulated)
			padding = output_header_field(out, 
			       ff_nr_samples_cumulated, padding);

		if (flags & ff_percent)
			padding = output_header_field(out,
			       ff_percent, padding);

		if (flags & ff_percent_cumulated)
			padding = output_header_field(out,
			       ff_percent_cumulated, padding);

		if (flags & ff_diff)
			padding = output_header_field(out,
				ff_diff, padding);

		if (flags & ff_percent_details)
			padding = output_header_field(out,
			       ff_percent_details, padding);

		if (flags & ff_percent_cumulated_details)
			padding = output_header_field(out,
			       ff_percent_cumulated_details, padding);
	}

	// now the remaining field
	if (flags & ff_linenr_info)
		padding = output_header_field(out, ff_linenr_info, padding);

	if (flags & ff_image_name)
		padding = output_header_field(out, ff_image_name, padding);

	if (flags & ff_app_name)
		padding = output_header_field(out, ff_app_name, padding);

	if (flags & ff_symb_name)
		padding = output_header_field(out, ff_symb_name, padding);

	out << "\n";
}


/// describe each possible field of colummned output.
// FIXME: use % of the screen width here. sum of % equal to 100, then calculate
// ratio between 100 and the selected % to grow non fixed field use also
// lib[n?]curses to get the console width (look info source) (so on add a fixed
// field flags)
size_t formatter::
output_field(ostream & out, field_datum const & datum,
             format_flags fl, size_t padding, bool hide_immutable)
{
	if (!hide_immutable) {
		out << string(padding, ' ');

		field_description const & field(format_map[fl]);
		string str = (this->*field.formatter)(datum);
		out << str;

		// at least one separator char
		padding = 1;
		if (str.length() < field.width)
			padding = field.width - str.length();
	} else {
		field_description const & field(format_map[fl]);
		padding += field.width;
	}

	return padding;
}

 
size_t formatter::
output_header_field(ostream & out, format_flags fl, size_t padding)
{
	out << string(padding, ' ');

	field_description const & field(format_map[fl]);
	out << field.header_name;

	// at least one separator char
	padding = 1;
	if (field.header_name.length() < field.width)
		padding = field.width - field.header_name.length();

	return padding;
}
 

string formatter::format_vma(field_datum const & f)
{
	return get_vma(f.sample.vma, vma_64);
}

 
string formatter::format_symb_name(field_datum const & f)
{
	return symbol_names.demangle(f.symbol.name);
}


string formatter::format_image_name(field_datum const & f)
{
	return get_image_name(f.symbol.image_name, long_filenames);
}

 
string formatter::format_app_name(field_datum const & f)
{
	return get_image_name(f.symbol.app_name, long_filenames);
}

 
string formatter::format_linenr_info(field_datum const & f)
{
	return get_linenr_info(f.sample.file_loc, long_filenames);
}

 
string formatter::format_nr_samples(field_datum const & f)
{
	ostringstream out;
	out << f.sample.counts[f.pclass];
	return out.str();
}

 
string formatter::format_nr_cumulated_samples(field_datum const & f)
{
	if (f.diff == -INFINITY)
		return "---";
	ostringstream out;
	f.counts.cumulated_samples[f.pclass] += f.sample.counts[f.pclass];
	out << f.counts.cumulated_samples[f.pclass];
	return out.str();
}

 
string formatter::format_percent(field_datum const & f)
{
	if (f.diff == -INFINITY)
		return "---";
	return get_percent(f.sample.counts[f.pclass], f.counts.total[f.pclass]);
}

 
string formatter::format_cumulated_percent(field_datum const & f)
{
	if (f.diff == -INFINITY)
		return "---";
	f.counts.cumulated_percent[f.pclass] += f.sample.counts[f.pclass];

	return get_percent(f.counts.cumulated_percent[f.pclass],
	                   f.counts.total[f.pclass]);
}

 
string formatter::format_percent_details(field_datum const & f)
{
	return get_percent(f.sample.counts[f.pclass],
		f.counts.total[f.pclass]);
}

 
string formatter::format_cumulated_percent_details(field_datum const & f)
{
	f.counts.cumulated_percent_details[f.pclass] += f.sample.counts[f.pclass];

	return get_percent(f.counts.cumulated_percent_details[f.pclass],
	                   f.counts.total[f.pclass]);
}


string formatter::format_diff(field_datum const & f)
{
	if (f.diff == INFINITY) {
		ostringstream out;
		out << "+++";
		return out.str();
	} else if (f.diff == -INFINITY) {
		ostringstream out;
		out << "---";
		return out.str();
	}

	return ::format_percent(f.diff, percent_int_width,
                                percent_fract_width, true);
}


void formatter::
do_output(ostream & out, symbol_entry const & symb, sample_entry const & sample,
          counts_t & c, diff_array_t const & diffs, bool hide_immutable)
{
	size_t padding = 0;

	// first output the vma field
	field_datum datum(symb, sample, 0, c);
	if (flags & ff_vma)
		padding = output_field(out, datum, ff_vma, padding, false);

	// repeated fields for each profile class
	for (size_t pclass = 0 ; pclass < nr_classes; ++pclass) {
		field_datum datum(symb, sample, pclass, c, diffs[pclass]);

		if (flags & ff_nr_samples)
			padding = output_field(out, datum,
			       ff_nr_samples, padding, false);

		if (flags & ff_nr_samples_cumulated)
			padding = output_field(out, datum, 
			       ff_nr_samples_cumulated, padding, false);

		if (flags & ff_percent)
			padding = output_field(out, datum,
			       ff_percent, padding, false);

		if (flags & ff_percent_cumulated)
			padding = output_field(out, datum,
			       ff_percent_cumulated, padding, false);

		if (flags & ff_diff)
			padding = output_field(out, datum,
				ff_diff, padding, false);

		if (flags & ff_percent_details)
			padding = output_field(out, datum,
			       ff_percent_details, padding, false);

		if (flags & ff_percent_cumulated_details)
			padding = output_field(out, datum,
			       ff_percent_cumulated_details, padding, false);
	}

	// now the remaining field
	if (flags & ff_linenr_info)
		padding = output_field(out, datum, ff_linenr_info,
		       padding, false);

	if (flags & ff_image_name)
		padding = output_field(out, datum, ff_image_name,
		       padding, hide_immutable);

	if (flags & ff_app_name)
		padding = output_field(out, datum, ff_app_name,
		       padding, hide_immutable);

	if (flags & ff_symb_name)
		padding = output_field(out, datum, ff_symb_name,
		       padding, hide_immutable);

	out << "\n";
}
 

opreport_formatter::opreport_formatter(profile_container const & p)
	:
	profile(p),
	need_details(false)
{
	counts.total = profile.samples_count();
}

 
void opreport_formatter::show_details(bool on_off)
{
	need_details = on_off;
}


void opreport_formatter::output(ostream & out, symbol_entry const * symb)
{
	do_output(out, *symb, symb->sample, counts);

	if (need_details)
		output_details(out, symb);
}


void opreport_formatter::
output(ostream & out, symbol_collection const & syms)
{
	output_header(out);

	symbol_collection::const_iterator it = syms.begin();
	symbol_collection::const_iterator end = syms.end();
	for (; it != end; ++it)
		output(out, *it);
}


void opreport_formatter::
output_details(ostream & out, symbol_entry const * symb)
{
	counts_t c = counts;

	if (!global_percent)
		c.total = symb->sample.counts;

	// cumulated percent are relative to current symbol.
	c.cumulated_samples = count_array_t();
	c.cumulated_percent = count_array_t();

	sample_container::samples_iterator it = profile.begin(symb);
	sample_container::samples_iterator end = profile.end(symb);
	for (; it != end; ++it) {
		out << "  ";
		do_output(out, *symb, it->second, c, diff_array_t(), true);
	}
}

 
cg_formatter::cg_formatter(callgraph_container const & profile)
{
	counts.total = profile.samples_count();
}


void cg_formatter::output(ostream & out, cg_collection const & syms)
{
	// amount of spacing prefixing child and parent lines
	string const child_parent_prefix("  ");

	output_header(out);

	out << string(79, '-') << endl;

	cg_collection::const_iterator it;
	cg_collection::const_iterator end = syms.end();

	for (it = syms.begin(); it < end; ++it) {
		cg_symbol const & sym = *it;

		cg_symbol::children::const_iterator cit;
		cg_symbol::children::const_iterator cend = sym.callers.end();

		counts_t c;
		if (global_percent)
			c.total = counts.total;
		else
			c.total = sym.total_caller_count;

		for (cit = sym.callers.begin(); cit != cend; ++cit) {
			out << child_parent_prefix;
			do_output(out, *cit, cit->sample, c);
		}

		do_output(out, sym, sym.sample, counts);

		c = counts_t();
		if (global_percent)
			c.total = counts.total;
		else
			c.total = sym.total_callee_count;

		cend = sym.callees.end();

		for (cit = sym.callees.begin(); cit != cend; ++cit) {
			out << child_parent_prefix;
			do_output(out, *cit, cit->sample, c);
		}

		out << string(79, '-') << endl;
	}
}


diff_formatter::diff_formatter(diff_container const & profile)
{
	counts.total = profile.samples_count();
}


void diff_formatter::output(ostream & out, diff_collection const & syms)
{
	output_header(out);

	diff_collection::const_iterator it = syms.begin();
	diff_collection::const_iterator end = syms.end();
	for (; it != end; ++it)
		do_output(out, *it, it->sample, counts, it->diffs);
}


} // namespace format_output
