#include <math.h>
#include <string.h>
+#include "strutil.h"
#include "stats_tree.h"
enum _stat_tree_columns {
/* used to contain the registered stat trees */
static GHashTable *registry = NULL;
-/* writes into the buffers pointed by value, rate and percent
- the string representations of a node*/
-/*** DEPRECIATED ***/
-extern void
-stats_tree_get_strs_from_node(const stat_node *node, gchar *value, gchar *rate, gchar *percent)
-{
- float f;
-
- if (value) g_snprintf(value,NUM_BUF_SIZE,"%u",node->counter);
-
- if (rate) {
- *rate = '\0';
- if (node->st->elapsed > 0.0) {
- f = ((float)node->counter) / (float)node->st->elapsed;
- g_snprintf(rate,NUM_BUF_SIZE,"%f",f);
- }
- }
-
- if (percent) {
- *percent = '\0';
- if (node->parent->counter > 0) {
- f = (float)(((float)node->counter * 100.0) / node->parent->counter);
- g_snprintf(percent,NUM_BUF_SIZE,"%.2f%%",f);
- }
- }
-}
-
-
/* a text representation of a node
if buffer is NULL returns a newly allocated string */
extern gchar*
return maxlen;
}
-static gchar *format;
-
-/* populates the given GString with a tree representation of a branch given by node,
-using indent spaces as initial indentation */
-/*** DEPRECIATED ***/
-extern void
-stats_tree_branch_to_str(const stat_node *node, GString *s, guint indent)
-{
- stat_node *child;
- static gchar indentation[INDENT_MAX+1];
- static gchar value[NUM_BUF_SIZE];
- static gchar rate[NUM_BUF_SIZE];
- static gchar percent[NUM_BUF_SIZE];
-
- guint i = 0;
-
- if (indent == 0) {
- format = g_strdup_printf(" %%s%%-%us%%12s %%12s %%12s\n",stats_tree_branch_max_namelen(node,0));
- }
-
- stats_tree_get_strs_from_node(node, value, rate, percent);
-
- indent = indent > INDENT_MAX ? INDENT_MAX : indent;
-
- /* fill indentation with indent spaces */
- if (indent > 0) {
- while(i<indent)
- indentation[i++] = ' ';
- }
-
- indentation[i] = '\0';
-
- g_string_append_printf(s,format,
- indentation,node->name,value,rate,percent);
-
- if (node->children) {
- for (child = node->children; child; child = child->next ) {
- stats_tree_branch_to_str(child,s,indent+1);
- }
- }
-
- if (indent == 0) {
- g_free(format);
- }
-}
-
-
/* frees the resources allocated by a stat_tree node */
static void
free_stat_node(stat_node *node)
burst_bucket *bucket;
if (node->children) {
- for (child = node->children; child; child = next ) {
- /* child->next will be gone after free_stat_node, so cache it here */
- next = child->next;
- free_stat_node(child);
- }
+ for (child = node->children; child; child = next ) {
+ /* child->next will be gone after free_stat_node, so cache it here */
+ next = child->next;
+ free_stat_node(child);
+ }
}
if(node->st->cfg->free_node_pr) node->st->cfg->free_node_pr(node);
stat_node *next;
for (child = st->root.children; child; child = next) {
- /* child->next will be gone after free_stat_node, so cache it here */
- next = child->next;
+ /* child->next will be gone after free_stat_node, so cache it here */
+ next = child->next;
free_stat_node(child);
}
node->bt = node->bh;
node->bcount = 0;
node->max_burst = 0;
- node->burst_time = -1;
+ node->burst_time = -1.0;
node->name = g_strdup(name);
node->children = NULL;
static range_pair_t*
get_range(char *rngstr)
{
- gchar **split;
- range_pair_t *rng;
-
- split = g_strsplit((gchar*)rngstr,"-",2);
-
- /* empty string */
- if (split[0] == NULL) {
- g_strfreev(split);
- return NULL;
- }
-
- rng = (range_pair_t *)g_malloc(sizeof(range_pair_t));
-
- if (split[1] == NULL) {
- /* means we have a non empty string with no delimiter
- * so it must be a single number */
- rng->floor = (gint)strtol(split[0],NULL,10);
- rng->ceil = rng->floor;
- } else {
- /* string == "X-?" */
- if (*(split[0]) != '\0') {
- rng->floor = (gint)strtol(split[0],NULL,10);
- } else
- /* string == "-?" */
- rng->floor = G_MININT;
-
- /* string != "?-" */
- if (*(split[1]) != '\0') {
- rng->ceil = (gint)strtol(split[1],NULL,10);
- } else
- /* string == "?-" */
- rng->ceil = G_MAXINT;
- }
- g_strfreev(split);
+ gchar **split;
+ range_pair_t *rng;
+
+ split = g_strsplit((gchar*)rngstr,"-",2);
+
+ /* empty string */
+ if (split[0] == NULL) {
+ g_strfreev(split);
+ return NULL;
+ }
+
+ rng = (range_pair_t *)g_malloc(sizeof(range_pair_t));
+
+ if (split[1] == NULL) {
+ /* means we have a non empty string with no delimiter
+ * so it must be a single number */
+ rng->floor = (gint)strtol(split[0],NULL,10);
+ rng->ceil = rng->floor;
+ } else {
+ /* string == "X-?" */
+ if (*(split[0]) != '\0') {
+ rng->floor = (gint)strtol(split[0],NULL,10);
+ } else
+ /* string == "-?" */
+ rng->floor = G_MININT;
+
+ /* string != "?-" */
+ if (*(split[1]) != '\0') {
+ rng->ceil = (gint)strtol(split[1],NULL,10);
+ } else
+ /* string == "?-" */
+ rng->ceil = G_MAXINT;
+ }
+ g_strfreev(split);
return rng;
}
stat_node *node = NULL;
stat_node *parent = NULL;
stat_node *child = NULL;
- gint floor, ceil;
+ gint stat_floor, stat_ceil;
if (parent_id >= 0 && parent_id < (int) st->parents->len) {
parent = (stat_node *)g_ptr_array_index(st->parents,parent_id);
node->st_flags |= ST_FLG_AVERAGE;
for ( child = node->children; child; child = child->next) {
- floor = child->rng->floor;
- ceil = child->rng->ceil;
+ stat_floor = child->rng->floor;
+ stat_ceil = child->rng->ceil;
- if ( value_in_range >= floor && value_in_range <= ceil ) {
+ if ( value_in_range >= stat_floor && value_in_range <= stat_ceil ) {
child->counter++;
child->total += value_in_range;
if (child->minvalue > value_in_range) {
}
sep = buf;
- while (sep= strchr(sep,'/')) {
+ while ((sep = strchr(sep,'/')) != NULL) {
if (*(++sep)=='/') { /* escapeded slash - two slash characters after each other */
memmove(sep,sep+1,strlen(sep));
}
case ST_SORT_COL_BURSTRATE: return COL_BURSTRATE;
}
return COL_COUNT; /* nothing specific set */
-}
+}
extern gboolean
stats_tree_is_default_sort_DESC (stats_tree *st)
return st->st_flags&ST_FLG_SORT_DESC;
}
-extern gchar*
-stats_tree_get_column_name (gint index)
+extern const gchar*
+stats_tree_get_column_name (gint col_index)
{
- switch (index) {
+ switch (col_index) {
case COL_NAME: return "Topic / Item";
case COL_COUNT: return "Count";
case COL_AVERAGE: return "Average";
case COL_PERCENT: return "Percent";
case COL_BURSTRATE: return prefs.st_burst_showcount?"Burst count":"Burst rate";
case COL_BURSTTIME: return "Burst start";
- default: return "(Unknown)";
+ default: return "(Unknown)";
}
}
extern gint
-stats_tree_get_column_size (gint index)
-{
- if (index==COL_NAME) {
- return 36; /* but caller should really call stats_tree_branch_max_namelen() */
- }
- if (index<N_COLUMNS) {
- return 12; /* all numerica values this size */
- }
- return 0; /* invalid column */
-}
-
-extern gboolean
-stats_tree_is_sortable_column (gint index)
+stats_tree_get_column_size (gint col_index)
{
- switch (index) {
- case COL_NAME:
- case COL_COUNT:
- case COL_AVERAGE:
- case COL_MIN:
- case COL_MAX:
- case COL_BURSTRATE: return TRUE;
- default: return FALSE;
+ if (col_index==COL_NAME) {
+ return 36; /* but caller should really call stats_tree_branch_max_namelen() */
}
+ if (col_index<N_COLUMNS) {
+ return 12; /* all numerical values are this size */
+ }
+ return 0; /* invalid column */
}
extern gchar**
stats_tree_get_values_from_node (const stat_node* node)
{
- gchar **values = (gchar**) g_malloc0(sizeof(gchar*)*(node->st->num_columns));
+ gchar **values = (gchar**) g_malloc0(sizeof(gchar*)*(node->st->num_columns));
values[COL_NAME]= (node->st_flags&ST_FLG_ROOTCHILD)?stats_tree_get_displayname(node->name):g_strdup(node->name);
values[COL_COUNT]= g_strdup_printf("%u",node->counter);
stats_tree_sort_compare (const stat_node *a, const stat_node *b, gint sort_column,
gboolean sort_descending)
{
- int result;
+ int result = 0;
float avg_a, avg_b;
if (prefs.st_sort_rng_nameonly&&(a->rng&&b->rng)) {
result = a->rng->floor - b->rng->floor;
if (sort_descending&&(!prefs.st_sort_rng_fixorder)) {
result= -result;
- }
+ }
return result;
}
}
break;
+ case COL_RATE:
+ case COL_PERCENT:
case COL_COUNT: result = a->counter - b->counter;
break;
break;
case COL_BURSTRATE: result = a->max_burst - b->max_burst;
+ break;
+
+ case COL_BURSTTIME: result = (a->burst_time>b->burst_time)?1:((a->burst_time<b->burst_time)?-1:0);
+ break;
+
+ default:
+ /* no sort comparison found for column - must update this switch statement */
+ g_assert_not_reached();
}
-
+
/* break tie between items with same primary search result */
if (!result) {
if (sort_column==COL_NAME) {
}
extern GString*
-stats_tree_format_as_str(const stats_tree* st, guint format,
+stats_tree_format_as_str(const stats_tree* st, st_format_type format_type,
gint sort_column, gboolean sort_descending)
{
int maxnamelen= stats_tree_branch_max_namelen(&st->root,0);
stat_node *child;
GString *s;
int count;
- gchar *separator;
+ gchar *separator = NULL;
- if (format==ST_FORMAT_XML) {
+ switch(format_type)
+ {
+ case ST_FORMAT_YAML:
+ s = g_string_new("---\n");
+ break;
+ case ST_FORMAT_XML:
s = g_string_new("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
- }
- else if (format==ST_FORMAT_CSV) {
+ break;
+ case ST_FORMAT_CSV:
s = g_string_new("\"level\",\"parent\",");
for (count = 0; count<st->num_columns; count++) {
g_string_append_printf(s,"\"%s\",",stats_tree_get_column_name(count));
}
g_string_append (s,"\n");
- }
- else if (format==ST_FORMAT_PLAIN) {
+ break;
+ case ST_FORMAT_PLAIN:
+ {
char fmt[16];
int sep_length;
for (count = 1; count<st->num_columns; count++) {
sep_length += stats_tree_get_column_size(count)+2;
}
- separator = g_malloc(sep_length+1);
+ separator = (gchar *)g_malloc(sep_length+1);
memset (separator, '=', sep_length);
separator[sep_length] = 0;
}
memset (separator, '-', sep_length);
g_string_append_printf(s,"\n%s\n",separator);
- }
- else {
+ }
+ break;
+ default:
return g_string_new("unknown format for stats_tree\n");
}
for (child = st->root.children; child; child = child->next ) {
- stats_tree_format_node_as_str(child,s,format,0,"",maxnamelen,sort_column,sort_descending);
+ stats_tree_format_node_as_str(child,s,format_type,0,"",maxnamelen,sort_column,sort_descending);
}
- if (format==ST_FORMAT_PLAIN) {
+ if (format_type==ST_FORMAT_PLAIN) {
g_string_append_printf(s,"\n%s\n",separator);
g_free(separator);
}
extern gint
stat_node_array_sortcmp (gconstpointer a, gconstpointer b, gpointer user_data)
{
- /* user_data is *guint value to st_flags */
- return stats_tree_sort_compare (*(stat_node**)a,*(stat_node**)b,
+ /* user_data is *guint value to st_flags */
+ return stats_tree_sort_compare (*(const stat_node**)a,*(const stat_node**)b,
((sortinfo*)user_data)->sort_column,((sortinfo*)user_data)->sort_descending);
-};
+}
static gchar*
clean_for_xml_tag (gchar *str)
{
gchar *s = str;
- while (s=strpbrk(s,"!\"#$%%&'()*+,/;<=>?@[\\]^`{|}~ ")) {
+ while ((s=strpbrk(s,"!\"#$%%&'()*+,/;<=>?@[\\]^`{|}~ ")) != NULL) {
*(s++) = '-';
}
return str;
}
-static GString*
-escape_xml_chars (gchar *str)
-{
- GString *s= g_string_new("");
- while (1) {
- switch (*str) {
- case 0: return s;
- case '<': g_string_append(s,"<");
- break;
- case '>': g_string_append(s,">");
- break;
- case '&': g_string_append(s,"&");
- break;
- case '\'': g_string_append(s,"'");
- break;
- case '"': g_string_append(s,""");
- break;
- default: g_string_append_c(s,*str);
- break;
- }
- str++;
- }
-
- return s;
-}
/** helper funcation to add note to formatted stats_tree */
-WS_DLL_PUBLIC void stats_tree_format_node_as_str(const stat_node *node, GString *s,
- guint format, guint indent, gchar *path, gint maxnamelen, gint sort_column,
- gboolean sort_descending)
+WS_DLL_PUBLIC void stats_tree_format_node_as_str(const stat_node *node,
+ GString *s,
+ st_format_type format_type,
+ guint indent,
+ const gchar *path,
+ gint maxnamelen,
+ gint sort_column,
+ gboolean sort_descending)
{
int count;
int num_columns= node->st->num_columns;
gchar **values= stats_tree_get_values_from_node(node);
stat_node *child;
sortinfo si;
+ gchar *full_path;
+ char fmt[16];
+
+ switch(format_type)
+ {
+ case ST_FORMAT_YAML:
+ if (indent) {
+ g_sprintf(fmt, "%%%ds%%s%%s", indent*4-2);
+ }
+ else {
+ strcpy(fmt, "%s%s%s");
+ }
+ g_string_append_printf(s, fmt, "", indent?"- ":"", "Description");
+ g_string_append_printf(s, ": \"%s\"\n", values[0]);
- if (format==ST_FORMAT_XML) {
- GString *itemname= escape_xml_chars(values[0]);
- g_string_append_printf(s,"<stat-node name=\"%s\"%s>\n",itemname->str,
+ for (count = 1; count<num_columns; count++) {
+ if (*values[count]) {
+ g_string_append_printf(s, fmt, "", indent?" ":"",
+ stats_tree_get_column_name(count));
+ g_string_append_printf(s, ": %s\n", values[count]);
+ }
+ }
+ if (node->children) {
+ g_string_append_printf(s, fmt, "", indent?" ":"", "Items:\n");
+ }
+ break;
+ case ST_FORMAT_XML:
+ {
+ char *itemname = xml_escape(values[0]);
+ g_string_append_printf(s,"<stat-node name=\"%s\"%s>\n",itemname,
node->rng?" isrange=\"true\"":"");
- g_string_free(itemname,TRUE);
- g_string_append(s,"");
+ g_free(itemname);
for (count = 1; count<num_columns; count++) {
gchar *colname= g_strdup(stats_tree_get_column_name(count));
g_string_append_printf(s,"<%s>",clean_for_xml_tag(colname));
g_string_append_printf(s,"%s</%s>\n",values[count],colname);
g_free(colname);
}
- }
- else if (format==ST_FORMAT_CSV) {
+ }
+ break;
+ case ST_FORMAT_CSV:
g_string_append_printf(s,"%d,\"%s\",\"%s\"",indent,path,values[0]);
for (count = 1; count<num_columns; count++) {
g_string_append_printf(s,",%s",values[count]);
}
g_string_append (s,"\n");
- }
- else if (format==ST_FORMAT_PLAIN) {
- char fmt[16];
-
+ break;
+ case ST_FORMAT_PLAIN:
g_sprintf (fmt,"%%%ds%%-%us",indent,maxnamelen-indent);
g_string_append_printf(s,fmt,"",values[0]);
for (count = 1; count<num_columns; count++) {
g_string_append_printf(s,fmt,values[count]);
}
g_string_append (s,"\n");
+ break;
}
indent++;
indent = indent > INDENT_MAX ? INDENT_MAX : indent;
- path= g_strdup_printf ("%s/%s",path,values[0]);
+ full_path= g_strdup_printf ("%s/%s",path,values[0]);
for (count = 0; count<num_columns; count++) {
g_free(values[count]);
si.sort_descending = sort_descending;
g_array_sort_with_data(Children,stat_node_array_sortcmp,&si);
for (count = 0; count<((int)Children->len); count++) {
- stats_tree_format_node_as_str(g_array_index(Children,stat_node*,count), s, format,
- indent, path, maxnamelen, sort_column, sort_descending);
+ stats_tree_format_node_as_str(g_array_index(Children,stat_node*,count), s, format_type,
+ indent, full_path, maxnamelen, sort_column, sort_descending);
}
g_array_free(Children,FALSE);
}
- g_free(path);
+ g_free(full_path);
- if (format==ST_FORMAT_XML) {
+ if (format_type==ST_FORMAT_XML) {
g_string_append(s,"</stat-node>\n");
}
}
-
-
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: ex: set shiftwidth=4 tabstop=8 noexpandtab:
+ * :indentSize=4:tabSize=8:noTabs=false:
+ */