diff options
author | Alan Fitton <ajf@eth0.org.uk> | 2012-01-02 14:14:41 +0000 |
---|---|---|
committer | Alan Fitton <ajf@eth0.org.uk> | 2012-01-02 14:14:41 +0000 |
commit | cd3800287297bdcd9fb8c90ee01a2414be3b9312 (patch) | |
tree | 93c4718a5f8dab79f9fd3c0af22c7ab1fc892a26 /src/util.c | |
parent | 8259ceddd02f76a337bb7037cdf5b86872ad09c6 (diff) |
change units to the IEC standard (and the Ubuntu units policy) for base2 (/1024) - KiB/GiB etc. this is instead of KB/s etc which Windows and many other apps use for base2. I've tried to fix up the translations as best as I can.
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 388 |
1 files changed, 241 insertions, 147 deletions
@@ -17,7 +17,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* Most of these functions are taken from the Transmission Project. */ +/* Many of these functions are taken from the Transmission Project. */ #include <stdlib.h> #include <math.h> @@ -33,6 +33,138 @@ #include "util.h" +/*** +**** The code for formatting size and speeds, taken from Transmission. +***/ + +const int disk_K = 1024; +const char * disk_K_str = N_("KiB"); +const char * disk_M_str = N_("MiB"); +const char * disk_G_str = N_("GiB"); +const char * disk_T_str = N_("TiB"); + +const int speed_K = 1024; +const char * speed_K_str = N_("KiB/s"); +const char * speed_M_str = N_("MiB/s"); +const char * speed_G_str = N_("GiB/s"); +const char * speed_T_str = N_("TiB/s"); + +struct formatter_unit +{ + char * name; + gint64 value; +}; + +struct formatter_units +{ + struct formatter_unit units[4]; +}; + +enum { TR_FMT_KB, TR_FMT_MB, TR_FMT_GB, TR_FMT_TB }; + +static void +formatter_init( struct formatter_units * units, + unsigned int kilo, + const char * kb, const char * mb, + const char * gb, const char * tb ) +{ + guint64 value = kilo; + units->units[TR_FMT_KB].name = g_strdup( kb ); + units->units[TR_FMT_KB].value = value; + + value *= kilo; + units->units[TR_FMT_MB].name = g_strdup( mb ); + units->units[TR_FMT_MB].value = value; + + value *= kilo; + units->units[TR_FMT_GB].name = g_strdup( gb ); + units->units[TR_FMT_GB].value = value; + + value *= kilo; + units->units[TR_FMT_TB].name = g_strdup( tb ); + units->units[TR_FMT_TB].value = value; +} + +static char* +formatter_get_size_str( const struct formatter_units * u, + char * buf, gint64 bytes, size_t buflen ) +{ + int precision; + double value; + const char * units; + const struct formatter_unit * unit; + + if( bytes < u->units[1].value ) unit = &u->units[0]; + else if( bytes < u->units[2].value ) unit = &u->units[1]; + else if( bytes < u->units[3].value ) unit = &u->units[2]; + else unit = &u->units[3]; + + value = (double)bytes / unit->value; + units = unit->name; + if( unit->value == 1 ) + precision = 0; + else if( value < 100 ) + precision = 2; + else + precision = 1; + tr_snprintf( buf, buflen, "%.*f %s", precision, value, units ); + return buf; +} + +static struct formatter_units size_units; + +void +tr_formatter_size_init( unsigned int kilo, + const char * kb, const char * mb, + const char * gb, const char * tb ) +{ + formatter_init( &size_units, kilo, kb, mb, gb, tb ); +} + +char* +tr_formatter_size_B( char * buf, gint64 bytes, size_t buflen ) +{ + return formatter_get_size_str( &size_units, buf, bytes, buflen ); +} + +static struct formatter_units speed_units; + +unsigned int tr_speed_K = 0u; + +void +tr_formatter_speed_init( unsigned int kilo, + const char * kb, const char * mb, + const char * gb, const char * tb ) +{ + tr_speed_K = kilo; + formatter_init( &speed_units, kilo, kb, mb, gb, tb ); +} + +char* +tr_formatter_speed_KBps( char * buf, double KBps, size_t buflen ) +{ + const double K = speed_units.units[TR_FMT_KB].value; + double speed = KBps; + + if( speed <= 999.95 ) /* 0.0 KB to 999.9 KB */ + tr_snprintf( buf, buflen, "%d %s", (int)speed, speed_units.units[TR_FMT_KB].name ); + else { + speed /= K; + if( speed <= 99.995 ) /* 0.98 MB to 99.99 MB */ + tr_snprintf( buf, buflen, "%.2f %s", speed, speed_units.units[TR_FMT_MB].name ); + else if (speed <= 999.95) /* 100.0 MB to 999.9 MB */ + tr_snprintf( buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_MB].name ); + else { + speed /= K; + tr_snprintf( buf, buflen, "%.1f %s", speed, speed_units.units[TR_FMT_GB].name ); + } + } + + return buf; +} + +/* URL checkers. */ + gboolean is_magnet(gchar * string) { return g_str_has_prefix(string, "magnet:"); @@ -44,22 +176,40 @@ gboolean is_url(gchar * string) return g_regex_match_simple("^http[s]?://", string, 0, 0); } -void add_file_id_to_array(JsonObject * args, gchar * key, gint index) +/* + * Glib-ish Utility functions. + */ + +gchar *trg_base64encode(const gchar * filename) { - JsonArray *array; - if (json_object_has_member(args, key)) { - array = json_object_get_array_member(args, key); + GError *error = NULL; + GMappedFile *mf = g_mapped_file_new(filename, FALSE, &error); + gchar *b64out = NULL; + + if (error) { + g_error("%s", error->message); + g_error_free(error); } else { - array = json_array_new(); - json_object_set_array_member(args, key, array); + b64out = + g_base64_encode((guchar *) g_mapped_file_get_contents(mf), + g_mapped_file_get_length(mf)); } - json_array_add_int_element(array, index); + + g_mapped_file_unref(mf); + + return b64out; } -void g_str_slist_free(GSList * list) +gchar *trg_gregex_get_first(GRegex * rx, const gchar * src) { - g_slist_foreach(list, (GFunc) g_free, NULL); - g_slist_free(list); + GMatchInfo *mi = NULL; + gchar *dst = NULL; + g_regex_match(rx, src, 0, &mi); + if (mi) { + dst = g_match_info_fetch(mi, 1); + g_match_info_free(mi); + } + return dst; } GRegex *trg_uri_host_regex_new(void) @@ -70,6 +220,76 @@ GRegex *trg_uri_host_regex_new(void) G_REGEX_OPTIMIZE, 0, NULL); } +void g_str_slist_free(GSList * list) +{ + g_slist_foreach(list, (GFunc) g_free, NULL); + g_slist_free(list); +} + +void rm_trailing_slashes(gchar * str) +{ + if (!str) + return; + + int i, len; + if ((len = strlen(str)) < 1) + return; + + for (i = strlen(str) - 1; str[i]; i--) { + if (str[i] == '/') + str[i] = '\0'; + else + return; + } +} + +/* Working with torrents.. */ + +void add_file_id_to_array(JsonObject * args, gchar * key, gint index) +{ + JsonArray *array; + if (json_object_has_member(args, key)) { + array = json_object_get_array_member(args, key); + } else { + array = json_array_new(); + json_object_set_array_member(args, key, array); + } + json_array_add_int_element(array, index); +} + +/* GTK utilities. */ + +GtkWidget *gtr_combo_box_new_enum(const char *text_1, ...) +{ + GtkWidget *w; + GtkCellRenderer *r; + GtkListStore *store; + va_list vl; + const char *text; + va_start(vl, text_1); + + store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING); + + text = text_1; + if (text != NULL) + do { + const int val = va_arg(vl, int); + gtk_list_store_insert_with_values(store, NULL, INT_MAX, 0, val, + 1, text, -1); + text = va_arg(vl, const char *); + } + while (text != NULL); + + w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + r = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), r, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), r, "text", 1, NULL); + + /* cleanup */ + g_object_unref(store); + return w; +} + GtkWidget *my_scrolledwin_new(GtkWidget * child) { GtkWidget *scrolled_win = gtk_scrolled_window_new(NULL, NULL); @@ -80,16 +300,15 @@ GtkWidget *my_scrolledwin_new(GtkWidget * child) return scrolled_win; } -gchar *trg_gregex_get_first(GRegex * rx, const gchar * src) +/* gtk_widget_set_sensitive() was introduced in 2.18, we can have a minimum of + * 2.16 otherwise. */ + +void trg_widget_set_visible(GtkWidget * w, gboolean visible) { - GMatchInfo *mi = NULL; - gchar *dst = NULL; - g_regex_match(rx, src, 0, &mi); - if (mi) { - dst = g_match_info_fetch(mi, 1); - g_match_info_free(mi); - } - return dst; + if (visible) + gtk_widget_show(w); + else + gtk_widget_hide(w); } void trg_error_dialog(GtkWindow * parent, trg_response * response) @@ -125,6 +344,8 @@ gchar *make_error_message(JsonObject * response, int status) } } +/* Formatters and Transmission basic utility functions.. */ + char *tr_strlpercent(char *buf, double x, size_t buflen) { return tr_strpercent(buf, x, buflen); @@ -172,34 +393,6 @@ char *tr_strlratio(char *buf, double ratio, size_t buflen) return tr_strratio(buf, buflen, ratio, "\xE2\x88\x9E"); } -char *tr_strlsize(char *buf, guint64 size, size_t buflen) -{ - if (!size) - g_strlcpy(buf, _("None"), buflen); - else { - char *tmp = g_format_size_for_display(size); - g_strlcpy(buf, tmp, buflen); - g_free(tmp); - } - return buf; -} - -char *tr_strlspeed(char *buf, double kb_sec, size_t buflen) -{ - const double speed = kb_sec; - - if (speed < 1000.0) /* 0.0 KB to 999.9 KB */ - g_snprintf(buf, buflen, _("%.1f KB/s"), speed); - else if (speed < 102400.0) /* 0.98 MB to 99.99 MB */ - g_snprintf(buf, buflen, _("%.2f MB/s"), (speed / KILOBYTE_FACTOR)); - else if (speed < 1024000.0) /* 100.0 MB to 999.9 MB */ - g_snprintf(buf, buflen, _("%.1f MB/s"), (speed / MEGABYTE_FACTOR)); - else /* insane speeds */ - g_snprintf(buf, buflen, _("%.2f GB/s"), (speed / GIGABYTE_FACTOR)); - - return buf; -} - char *tr_strltime_short(char *buf, long seconds, size_t buflen) { int hours, minutes; @@ -337,102 +530,3 @@ evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) return r; #endif } - -void rm_trailing_slashes(gchar * str) -{ - if (!str) - return; - - int i, len; - if ((len = strlen(str)) < 1) - return; - - for (i = strlen(str) - 1; str[i]; i--) { - if (str[i] == '/') - str[i] = '\0'; - else - return; - } -} - -/* gtk_widget_set_sensitive() was introduced in 2.18, we can have a minimum of - * 2.16 otherwise. */ - -void trg_widget_set_visible(GtkWidget * w, gboolean visible) -{ - if (visible) - gtk_widget_show(w); - else - gtk_widget_hide(w); -} - -gdouble json_double_to_progress(JsonNode * n) -{ - return json_node_really_get_double(n) * 100.0; -} - -gdouble json_node_really_get_double(JsonNode * node) -{ - GValue a = { 0 }; - - json_node_get_value(node, &a); - switch (G_VALUE_TYPE(&a)) { - case G_TYPE_INT64: - return (gdouble) g_value_get_int64(&a); - case G_TYPE_DOUBLE: - return g_value_get_double(&a); - default: - return 0.0; - } -} - -gchar *trg_base64encode(const gchar * filename) -{ - GError *error = NULL; - GMappedFile *mf = g_mapped_file_new(filename, FALSE, &error); - gchar *b64out = NULL; - - if (error) { - g_error("%s", error->message); - g_error_free(error); - } else { - b64out = - g_base64_encode((guchar *) g_mapped_file_get_contents(mf), - g_mapped_file_get_length(mf)); - } - - g_mapped_file_unref(mf); - - return b64out; -} - -GtkWidget *gtr_combo_box_new_enum(const char *text_1, ...) -{ - GtkWidget *w; - GtkCellRenderer *r; - GtkListStore *store; - va_list vl; - const char *text; - va_start(vl, text_1); - - store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING); - - text = text_1; - if (text != NULL) - do { - const int val = va_arg(vl, int); - gtk_list_store_insert_with_values(store, NULL, INT_MAX, 0, val, - 1, text, -1); - text = va_arg(vl, const char *); - } - while (text != NULL); - - w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); - r = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), r, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(w), r, "text", 1, NULL); - - /* cleanup */ - g_object_unref(store); - return w; -} |