Add back the fix from revision 54693.
[metze/wireshark/wip.git] / epan / stats_tree.c
index d1db527485abbd0190ba4f575ef6ddc29a1370f7..83713c206473ccdcca476e838a1795a5e532571c 100644 (file)
@@ -43,6 +43,7 @@
 #include <math.h>
 #include <string.h>
 
+#include "strutil.h"
 #include "stats_tree.h"
 
 enum _stat_tree_columns {
@@ -61,34 +62,6 @@ 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*
@@ -131,53 +104,6 @@ stats_tree_branch_max_namelen(const stat_node *node, guint indent)
        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)
@@ -187,11 +113,11 @@ 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);
@@ -297,8 +223,8 @@ stats_tree_reinit(void *p)
        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);
        }
 
@@ -566,7 +492,7 @@ new_stat_node(stats_tree *st, const gchar *name, int parent_id,
        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;
@@ -828,40 +754,40 @@ stats_tree_get_abbr(const char *opt_arg)
 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;
 }
@@ -944,7 +870,7 @@ stats_tree_tick_range(stats_tree *st, const gchar *name, int parent_id,
        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);
@@ -972,10 +898,10 @@ stats_tree_tick_range(stats_tree *st, const gchar *name, int 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) {
@@ -1042,7 +968,7 @@ stats_tree_get_displayname (gchar* fullname)
        }
 
        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));
                }
@@ -1068,7 +994,7 @@ stats_tree_get_default_sort_col (stats_tree *st)
                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)
@@ -1076,10 +1002,10 @@ 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";
@@ -1089,40 +1015,26 @@ stats_tree_get_column_name (gint index)
                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);
@@ -1155,7 +1067,7 @@ extern gint
 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)) {
@@ -1163,7 +1075,7 @@ stats_tree_sort_compare (const stat_node *a, const stat_node *b, gint sort_colum
                result = a->rng->floor - b->rng->floor;
                if (sort_descending&&(!prefs.st_sort_rng_fixorder)) {
                        result= -result;
-               }               
+               }
                return result;
        }
 
@@ -1180,6 +1092,8 @@ stats_tree_sort_compare (const stat_node *a, const stat_node *b, gint sort_colum
                                                        }
                                                        break;
 
+               case COL_RATE:
+               case COL_PERCENT:
                case COL_COUNT:         result = a->counter - b->counter;
                                                        break;
 
@@ -1203,8 +1117,16 @@ stats_tree_sort_compare (const stat_node *a, const stat_node *b, gint sort_colum
                                                        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) {
@@ -1236,26 +1158,32 @@ stats_tree_sort_compare (const stat_node *a, const stat_node *b, gint sort_colum
 }
 
 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;
 
@@ -1263,7 +1191,7 @@ stats_tree_format_as_str(const stats_tree* st, guint format,
                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;
 
@@ -1278,17 +1206,18 @@ stats_tree_format_as_str(const stats_tree* st, guint format,
                }
                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);
        }
@@ -1306,80 +1235,84 @@ points to a st_flags value */
 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,"&lt;");
-                                               break;
-                       case '>':       g_string_append(s,"&gt;");
-                                               break;
-                       case '&':       g_string_append(s,"&amp;");
-                                               break;
-                       case '\'':      g_string_append(s,"&apos;");
-                                               break;
-                       case '"':       g_string_append(s,"&quot;");
-                                               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++) {
@@ -1387,11 +1320,12 @@ WS_DLL_PUBLIC void stats_tree_format_node_as_str(const stat_node *node, GString
                        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]);
@@ -1407,17 +1341,27 @@ WS_DLL_PUBLIC void stats_tree_format_node_as_str(const stat_node *node, GString
                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:
+ */