summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorGravatar Alan Fitton <ajf@eth0.org.uk>2012-01-02 14:14:41 +0000
committerGravatar Alan Fitton <ajf@eth0.org.uk>2012-01-02 14:14:41 +0000
commitcd3800287297bdcd9fb8c90ee01a2414be3b9312 (patch)
tree93c4718a5f8dab79f9fd3c0af22c7ab1fc892a26 /src/util.c
parent8259ceddd02f76a337bb7037cdf5b86872ad09c6 (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.c388
1 files changed, 241 insertions, 147 deletions
diff --git a/src/util.c b/src/util.c
index b103cff..ef03482 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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;
-}