/* Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * This file is part of PowerTOP * * This program file is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program in a file named COPYING; if not, write to the * Free Software Foundation, Inc, * 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * or just google for it. * * HTML report generator. * Written by Igor Zhbanov * 2012.10 */ #define _BSD_SOURCE /* Uncomment to disable asserts */ /*#define NDEBUG*/ #include #include #include #include "report-formatter-html.h" #include "css.h" /* For HTML-report header */ /* ************************************************************************ */ #ifdef EXTERNAL_CSS_FILE /* Where is it defined? */ static const char report_html_alternative_head[] = "\n" "\n" "\n" "PowerTOP report\n" "\n" "\n" "\n"; #endif /* EXTERNAL_CSS_FILE */ /* ************************************************************************ */ static const char report_html_footer[] = "\n" "\n"; /* ************************************************************************ */ void report_formatter_html::init_markup() { /* stype id */ set_section(SECTION_DEFAULT); set_section(SECTION_SYSINFO, "system"); set_section(SECTION_CPUIDLE, "cpuidle"); set_section(SECTION_CPUFREQ, "cpufreq"); set_section(SECTION_DEVPOWER, "device"); set_section(SECTION_SOFTWARE, "software"); set_section(SECTION_SUMMARY, "summary"); set_section(SECTION_DEVFREQ, "devfreq"); set_section(SECTION_TUNING, "tuning"); /* ttype width */ set_table(TABLE_DEFAULT, ""); set_table(TABLE_WIDE, "100%"); /* ctype is_header, width, colspan */ set_cell(CELL_DEFAULT); set_cell(CELL_SEPARATOR, false, "2%"); set_cell(CELL_SYSINFO, false, "20%"); set_cell(CELL_FIRST_PACKAGE_HEADER, true, "25%", 2); set_cell(CELL_EMPTY_PACKAGE_HEADER, true, "", 2); set_cell(CELL_CORE_HEADER, true, "25%", 2); set_cell(CELL_CPU_CSTATE_HEADER, true, "", 3); set_cell(CELL_CPU_PSTATE_HEADER, true, "", 2); set_cell(CELL_STATE_NAME, false, "10%"); set_cell(CELL_EMPTY_PACKAGE_STATE, false, "", 2); set_cell(CELL_PACKAGE_STATE_VALUE); set_cell(CELL_CORE_STATE_VALUE); set_cell(CELL_CPU_STATE_VALUE); set_cell(CELL_DEVPOWER_HEADER, true, "10%"); set_cell(CELL_DEVPOWER_DEV_NAME, true); set_cell(CELL_DEVPOWER_POWER); set_cell(CELL_DEVPOWER_UTIL); set_cell(CELL_DEVACTIVITY_PROCESS, true, "40%"); set_cell(CELL_DEVACTIVITY_DEVICE, true); set_cell(CELL_SOFTWARE_HEADER, true, "10%"); set_cell(CELL_SOFTWARE_PROCESS, true, "10%"); set_cell(CELL_SOFTWARE_DESCRIPTION, true); set_cell(CELL_SOFTWARE_POWER); set_cell(CELL_SUMMARY_HEADER, true, "10%"); set_cell(CELL_SUMMARY_CATEGORY, true, "10%"); set_cell(CELL_SUMMARY_DESCRIPTION, true); set_cell(CELL_SUMMARY_ITEM); set_cell(CELL_TUNABLE_HEADER, true); } /* ************************************************************************ */ const char * report_formatter_html::get_row_style(row_type rtype) { switch (rtype) { case ROW_SYSINFO: return get_style_pair("system_even", "system_odd"); case ROW_DEVPOWER: return get_style_pair("device_even", "device_odd"); case ROW_SOFTWARE: case ROW_SUMMARY: return get_style_pair("process_even", "process_odd"); case ROW_TUNABLE: return get_style_pair("tunable_even", "tunable_odd"); case ROW_TUNABLE_BAD: return get_style_pair("tunable_even_bad", "tunable_odd_bad"); default: return ""; }; } /* ************************************************************************ */ const char * report_formatter_html::get_cell_style(cell_type ctype) { switch (ctype) { case CELL_FIRST_PACKAGE_HEADER: case CELL_EMPTY_PACKAGE_HEADER: return "package_header"; case CELL_CORE_HEADER: return "core_header"; case CELL_CPU_CSTATE_HEADER: case CELL_CPU_PSTATE_HEADER: return "cpu_header"; case CELL_STATE_NAME: return get_style_pair("cpu_even_freq", "cpu_odd_freq"); case CELL_PACKAGE_STATE_VALUE: return get_style_pair("package_even", "package_odd"); case CELL_CORE_STATE_VALUE: return get_style_pair("core_even", "core_odd"); case CELL_CPU_STATE_VALUE: return get_style_quad("cpu_even_even", "cpu_even_odd", "cpu_odd_even", "cpu_odd_odd", cpu_nr); case CELL_DEVPOWER_DEV_NAME: case CELL_DEVACTIVITY_PROCESS: case CELL_DEVACTIVITY_DEVICE: return "device"; case CELL_DEVPOWER_POWER: return "device_power"; case CELL_DEVPOWER_UTIL: return "device_util"; case CELL_SOFTWARE_PROCESS: case CELL_SOFTWARE_DESCRIPTION: case CELL_SUMMARY_CATEGORY: case CELL_SUMMARY_DESCRIPTION: return "process"; case CELL_SOFTWARE_POWER: case CELL_SUMMARY_ITEM: return "process_power"; case CELL_TUNABLE_HEADER: return "tunable"; default: return ""; }; } /* ************************************************************************ */ report_formatter_html::report_formatter_html() { init_markup(); add_doc_header(); } /* ************************************************************************ */ const char * report_formatter_html::get_style_pair(const char *even, const char *odd) { if (!(table_row_number & 1) && even) return even; if ((table_row_number & 1) && odd) return odd; return ""; } /* ************************************************************************ */ const char * report_formatter_html::get_style_quad(const char *even_even, const char *even_odd, const char *odd_even, const char *odd_odd, int alt_cell_number) { int cell; cell = (alt_cell_number != -1 ? alt_cell_number : table_cell_number); if (!(table_row_number & 1) && !(cell & 1) && even_even) return even_even; if (!(table_row_number & 1) && (cell & 1) && even_odd) return even_odd; if ((table_row_number & 1) && !(cell & 1) && odd_even) return odd_even; if ((table_row_number & 1) && (cell & 1) && odd_odd) return odd_odd; return ""; } /* ************************************************************************ */ void report_formatter_html::finish_report() { add_doc_footer(); } /* ************************************************************************ */ void report_formatter_html::set_section(section_type stype, const char *id) { sections[stype].id = id; } /* ************************************************************************ */ void report_formatter_html::set_table(table_type ttype, const char *width) { tables[ttype].width = width; } /* ************************************************************************ */ void report_formatter_html::set_cell(cell_type ctype, bool is_header, const char *width, int colspan) { cells[ctype].is_header = is_header; cells[ctype].width = width; cells[ctype].colspan = colspan; } /* ************************************************************************ */ void report_formatter_html::add_doc_header() { #ifdef EXTERNAL_CSS_FILE /* Where is it defined? */ add_exact(report_html_alternative_head); #else /* !EXTERNAL_CSS_FILE */ add_exact(css); #endif /* !EXTERNAL_CSS_FILE */ } /* ************************************************************************ */ void report_formatter_html::add_doc_footer() { add_exact(report_html_footer); } /* ************************************************************************ */ void report_formatter_html::add_header(const char *header, int level) { addf_exact("", level); add(header); addf_exact("\n", level); } /* ************************************************************************ */ void report_formatter_html::begin_section(section_type stype) { if (sections[stype].id[0]) addf_exact("
", sections[stype].id); else add_exact("
"); } /* ************************************************************************ */ void report_formatter_html::end_section() { add_exact("
\n\n"); } /* ************************************************************************ */ void report_formatter_html::begin_table(table_type ttype) { table_row_number = 0; add_exact("\n"); } /* ************************************************************************ */ void report_formatter_html::end_table() { add_exact("\n\n"); } /* ************************************************************************ */ void report_formatter_html::begin_row(row_type rtype) { const char *row_style; table_cell_number = 0; add_exact("\n"); } /* ************************************************************************ */ void report_formatter_html::end_row() { add_exact("\n"); table_row_number++; } /* ************************************************************************ */ void report_formatter_html::begin_cell(cell_type ctype) { const char *cell_style; current_cell = ctype; if (cells[ctype].is_header) add_exact("\t 1) addf_exact(" colspan=\"%d\"", cells[ctype].colspan); cell_style = get_cell_style(ctype); if (cell_style[0]) addf_exact(" class=\"%s\"", cell_style); add_exact(">"); } /* ************************************************************************ */ void report_formatter_html::end_cell() { if (!cells[current_cell].is_header) add_exact("\n"); else add_exact("\n"); table_cell_number++; } /* ************************************************************************ */ void report_formatter_html::add_empty_cell() { add_exact(" "); } /* ************************************************************************ */ void report_formatter_html::begin_paragraph() { add_exact("

"); } /* ************************************************************************ */ void report_formatter_html::end_paragraph() { add_exact("

\n"); } /* ************************************************************************ */ std::string report_formatter_html::escape_string(const char *str) { std::string res; assert(str); for (const char *i = str; *i; i++) { switch (*i) { case '<': res += "<"; continue; case '>': res += ">"; continue; case '&': res += "&"; continue; #ifdef REPORT_HTML_ESCAPE_QUOTES case '"': res += """; continue; case '\'': res += "'"; continue; #endif /* REPORT_HTML_ESCAPE_QUOTES */ } res += *i; } return res; } /* ************************************************************************ */ void report_formatter_html::set_cpu_number(int nr) { assert(nr >= 0); cpu_nr = nr; }