From 62a5ed49cc187120793ea50e0eec4e18c8bc0441 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 9 Dec 2018 12:09:40 -0600 Subject: [PATCH] Fix possible truncation misc.c->output_dyn_value + use Kibytes output_dyn_value now requires the count for number of units Binary scale now shows Kibibytes instead of kilobytes (g#1742) Fixes output for negative values as well Change-Id: I8aa896860e97d2453fa35069e2dfe1caac60109f --- apps/debug_menu.c | 4 +-- apps/lang/english.lang | 66 ++++++++++++++++++++++++++++++++------- apps/menus/main_menu.c | 32 +++++++++---------- apps/misc.c | 42 ++++++++++++++----------- apps/misc.h | 10 ++++-- apps/recorder/recording.c | 2 +- apps/screens.c | 2 +- apps/talk.c | 2 +- 8 files changed, 106 insertions(+), 54 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 0dec3cd738..362d3fbf3e 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -1326,11 +1326,11 @@ static int disk_callback(int btn, struct gui_synclist *lists) simplelist_addline( "Blocks: 0x%08lx", card->numblocks); output_dyn_value(pbuf, sizeof pbuf, card->speed / 1000, - kbit_units, false); + kbit_units, 3, false); simplelist_addline( "Speed: %s", pbuf); output_dyn_value(pbuf, sizeof pbuf, card->taac, - nsec_units, false); + nsec_units, 3, false); simplelist_addline( "Taac: %s", pbuf); simplelist_addline( diff --git a/apps/lang/english.lang b/apps/lang/english.lang index d4e0697667..f4f1b12032 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -8441,44 +8441,44 @@ id: LANG_KILOBYTE - desc: a unit postfix, also voiced + desc: deprecated user: core - *: "KB" + *: "" - *: "KB" + *: "" - *: "kilobyte" + *: "" id: LANG_MEGABYTE - desc: a unit postfix, also voiced + desc: deprecated user: core - *: "MB" + *: "" - *: "MB" + *: "" - *: "megabyte" + *: "" id: LANG_GIGABYTE - desc: a unit postfix, also voiced + desc: deprecated user: core - *: "GB" + *: "" - *: "GB" + *: "" - *: "gigabyte" + *: "" @@ -13647,3 +13647,45 @@ *: "Disable Touch" + + id: LANG_KIBIBYTE + desc: a unit postfix, also voiced + user: core + + *: "KiB" + + + *: "KiB" + + + *: "kibibyte" + + + + id: LANG_MEBIBYTE + desc: a unit postfix, also voiced + user: core + + *: "MiB" + + + *: "MiB" + + + *: "mebibyte" + + + + id: LANG_GIBIBYTE + desc: a unit postfix, also voiced + user: core + + *: "GiB" + + + *: "GiB" + + + *: "gibibyte" + + diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c index 139667cef4..a5196020a0 100644 --- a/apps/menus/main_menu.c +++ b/apps/menus/main_menu.c @@ -181,8 +181,8 @@ static const char* info_getname(int selected_item, void *data, case INFO_BUFFER: /* buffer */ { - long kib = audio_buffer_size() / 1024; /* to KiB */ - output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true); + long kib = audio_buffer_size() >> 10; /* to KiB */ + output_dyn_value(s1, sizeof(s1), kib, kibyte_units, 3, true); snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1); } break; @@ -217,12 +217,12 @@ static const char* info_getname(int selected_item, void *data, break; case INFO_DISK1: /* disk usage 1 */ #ifdef HAVE_MULTIVOLUME - output_dyn_value(s1, sizeof s1, info->free, kbyte_units, true); - output_dyn_value(s2, sizeof s2, info->size, kbyte_units, true); + output_dyn_value(s1, sizeof s1, info->free, kibyte_units, 3, true); + output_dyn_value(s2, sizeof s2, info->size, kibyte_units, 3, true); snprintf(buffer, buffer_len, "%s %s/%s", str(LANG_DISK_NAME_INTERNAL), s1, s2); #else - output_dyn_value(s1, sizeof s1, info->free, kbyte_units, true); + output_dyn_value(s1, sizeof s1, info->free, kibyte_units, 3, true); snprintf(buffer, buffer_len, SIZE_FMT, str(LANG_DISK_FREE_INFO), s1); #endif break; @@ -230,8 +230,8 @@ static const char* info_getname(int selected_item, void *data, #ifdef HAVE_MULTIVOLUME if (info->size2) { - output_dyn_value(s1, sizeof s1, info->free2, kbyte_units, true); - output_dyn_value(s2, sizeof s2, info->size2, kbyte_units, true); + output_dyn_value(s1, sizeof s1, info->free2, kibyte_units, 3, true); + output_dyn_value(s2, sizeof s2, info->size2, kibyte_units, 3, true); snprintf(buffer, buffer_len, "%s %s/%s", str(LANG_DISK_NAME_MMC), s1, s2); } @@ -241,7 +241,7 @@ static const char* info_getname(int selected_item, void *data, str(LANG_NOT_PRESENT)); } #else - output_dyn_value(s1, sizeof s1, info->size, kbyte_units, true); + output_dyn_value(s1, sizeof s1, info->size, kibyte_units, 3, true); snprintf(buffer, buffer_len, SIZE_FMT, str(LANG_DISK_SIZE_INFO), s1); #endif break; @@ -263,8 +263,8 @@ static int info_speak_item(int selected_item, void * data) case INFO_BUFFER: /* buffer */ { talk_id(LANG_BUFFER_STAT, false); - long kib = audio_buffer_size() / 1024; /* to KiB */ - output_dyn_value(NULL, 0, kib, kbyte_units, true); + long kib = audio_buffer_size() >> 10; /* to KiB */ + output_dyn_value(NULL, 0, kib, kibyte_units, 3, true); break; } case INFO_BATTERY: /* battery */ @@ -303,12 +303,12 @@ static int info_speak_item(int selected_item, void * data) case INFO_DISK1: /* disk 1 */ #ifdef HAVE_MULTIVOLUME talk_ids(false, LANG_DISK_NAME_INTERNAL, LANG_DISK_FREE_INFO); - output_dyn_value(NULL, 0, info->free, kbyte_units, true); + output_dyn_value(NULL, 0, info->free, kibyte_units, 3, true); talk_id(LANG_DISK_SIZE_INFO, true); - output_dyn_value(NULL, 0, info->size, kbyte_units, true); + output_dyn_value(NULL, 0, info->size, kibyte_units, 3, true); #else talk_id(LANG_DISK_FREE_INFO, false); - output_dyn_value(NULL, 0, info->free, kbyte_units, true); + output_dyn_value(NULL, 0, info->free, kibyte_units, 3, true); #endif break; case INFO_DISK2: /* disk 2 */ @@ -317,14 +317,14 @@ static int info_speak_item(int selected_item, void * data) if (info->size2) { talk_id(LANG_DISK_FREE_INFO, true); - output_dyn_value(NULL, 0, info->free2, kbyte_units, true); + output_dyn_value(NULL, 0, info->free2, kibyte_units, 3, true); talk_id(LANG_DISK_SIZE_INFO, true); - output_dyn_value(NULL, 0, info->size2, kbyte_units, true); + output_dyn_value(NULL, 0, info->size2, kibyte_units, 3, true); } else talk_id(LANG_NOT_PRESENT, true); #else talk_id(LANG_DISK_SIZE_INFO, false); - output_dyn_value(NULL, 0, info->size, kbyte_units, true); + output_dyn_value(NULL, 0, info->size, kibyte_units, 3, true); #endif break; diff --git a/apps/misc.c b/apps/misc.c index 477efc6313..b3ae8e9af5 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -110,41 +110,47 @@ const unsigned char * const byte_units[] = { ID2P(LANG_BYTE), - ID2P(LANG_KILOBYTE), - ID2P(LANG_MEGABYTE), - ID2P(LANG_GIGABYTE) + ID2P(LANG_KIBIBYTE), + ID2P(LANG_MEBIBYTE), + ID2P(LANG_GIBIBYTE) }; -const unsigned char * const * const kbyte_units = &byte_units[1]; +const unsigned char * const * const kibyte_units = &byte_units[1]; /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" * units) if possible, and 3 significant digits are shown. If a buffer is * given, the result is snprintf()'d into that buffer, otherwise the result is * voiced.*/ -char *output_dyn_value(char *buf, int buf_size, int value, - const unsigned char * const *units, bool bin_scale) +char *output_dyn_value(char *buf, + int buf_size, + int value, + const unsigned char * const *units, + unsigned int unit_count, + bool binary_scale) { - int scale = bin_scale ? 1024 : 1000; - int fraction = 0; - int unit_no = 0; + unsigned int scale = binary_scale ? 1024 : 1000; + unsigned int fraction = 0; + unsigned int unit_no = 0; + unsigned int value_abs = (value < 0) ? -value : value; char tbuf[5]; - while (value >= scale) + while (value_abs >= scale && unit_no < (unit_count - 1)) { - fraction = value % scale; - value /= scale; + fraction = value_abs % scale; + value_abs /= scale; unit_no++; } - if (bin_scale) - fraction = fraction * 1000 / 1024; + + value = (value < 0) ? -value_abs : value_abs; /* preserve sign */ + fraction = (fraction * 1000 / scale) / 10; - if (value >= 100 || !unit_no) + if (value_abs >= 100 || fraction >= 100 || !unit_no) tbuf[0] = '\0'; - else if (value >= 10) - snprintf(tbuf, sizeof(tbuf), "%01d", fraction / 100); + else if (value_abs >= 10) + snprintf(tbuf, sizeof(tbuf), "%01u", fraction / 10); else - snprintf(tbuf, sizeof(tbuf), "%02d", fraction / 10); + snprintf(tbuf, sizeof(tbuf), "%02u", fraction); if (buf) { diff --git a/apps/misc.h b/apps/misc.h index b13c0b15c6..6821c6debf 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -27,15 +27,19 @@ #include "screen_access.h" extern const unsigned char * const byte_units[]; -extern const unsigned char * const * const kbyte_units; +extern const unsigned char * const * const kibyte_units; /* Format a large-range value for output, using the appropriate unit so that * the displayed value is in the range 1 <= display < 1000 (1024 for "binary" * units) if possible, and 3 significant digits are shown. If a buffer is * given, the result is snprintf()'d into that buffer, otherwise the result is * voiced.*/ -char *output_dyn_value(char *buf, int buf_size, int value, - const unsigned char * const *units, bool bin_scale); +char *output_dyn_value(char *buf, + int buf_size, + int value, + const unsigned char * const *units, + unsigned int unit_count, + bool binary_scale); /* Format time into buf. * diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index b8f10dc83e..d47773071f 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -1756,7 +1756,7 @@ bool recording_screen(bool no_source) { output_dyn_value(buf2, sizeof buf2, num_recorded_bytes, - byte_units, true); + byte_units, 4, true); snprintf(buf, sizeof(buf), "%s %s", str(LANG_RECORDING_SIZE), buf2); } diff --git a/apps/screens.c b/apps/screens.c index e203b446cf..5fa92f5fbd 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -747,7 +747,7 @@ static const char* id3_get_info(int selected_item, void* data, val=id3->composer; break; case LANG_FILESIZE: /* not LANG_ID3_FILESIZE because the string is shared */ - output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, true); + output_dyn_value(buffer, buffer_len, id3->filesize, byte_units, 4, true); val=buffer; break; } diff --git a/apps/talk.c b/apps/talk.c index 910f355ff9..aae33283ae 100644 --- a/apps/talk.c +++ b/apps/talk.c @@ -1330,7 +1330,7 @@ int talk_value_decimal(long n, int unit, int decimals, bool enqueue) [UNIT_HERTZ] = VOICE_HERTZ, [UNIT_MB] - = LANG_MEGABYTE, + = LANG_MEBIBYTE, [UNIT_KBIT] = VOICE_KBIT_PER_SEC, [UNIT_PM_TICK]