Scripting: Normalize output of FormatBytes (#947)

* Scripting: Normalize output of FormatBytes

* lua: Add flag to use locale when formatting bytes

Co-Authored-By: ihaveahax <ian@ianburgwin.net>

---------

Co-authored-by: ihaveahax <ian@ianburgwin.net>
This commit is contained in:
Pk11 2026-03-18 10:39:29 -05:00 committed by GitHub
parent 22939ec6ad
commit d2445f0396
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 44 additions and 35 deletions

View File

@ -637,8 +637,12 @@ void FormatNumber(char* str, u64 number) { // str should be 32 byte in size
}
}
void FormatBytes(char* str, u64 bytes) { // str should be 32 byte in size, just to be safe
const char* units[] = {STR_BYTE, STR_KB, STR_MB, STR_GB};
void FormatBytes(char* str, u64 bytes, bool useLocale) { // str should be 32 byte in size, just to be safe
static const char* normalizedUnits[] = {" Byte", " kB", " MB", " GB"};
const char* localizedUnits[] = {STR_BYTE, STR_KB, STR_MB, STR_GB};
const char** units = useLocale ? localizedUnits : normalizedUnits;
const char *separator = useLocale ? STR_DECIMAL_SEPARATOR : ".";
if (bytes == (u64) -1) snprintf(str, 32, "%s", STR_INVALID);
else if (bytes < 1024) snprintf(str, 32, "%llu%s", bytes, units[0]);
@ -646,7 +650,7 @@ void FormatBytes(char* str, u64 bytes) { // str should be 32 byte in size, just
u32 scale = 1;
u64 bytes100 = (bytes * 100) >> 10;
for(; (bytes100 >= 1024*100) && (scale < 3); scale++, bytes100 >>= 10);
snprintf(str, 32, "%llu%s%llu%s", bytes100 / 100, STR_DECIMAL_SEPARATOR, (bytes100 % 100) / 10, units[scale]);
snprintf(str, 32, "%llu%s%llu%s", bytes100 / 100, separator, (bytes100 % 100) / 10, units[scale]);
}
}
@ -956,7 +960,7 @@ u32 ShowFileScrollPrompt(int n, const DirEntry** options, bool hide_ext, const c
while (true) {
for (int i = scroll; i < scroll+n_show; i++) {
char bytestr[16];
FormatBytes(bytestr, options[i]->size);
FormatBytes(bytestr, options[i]->size, true);
char content_str[UTF_BUFFER_BYTESIZE(fname_len)];
char temp_str[256];

View File

@ -81,7 +81,7 @@ void WordWrapString(char* str, int llen);
void ResizeString(char* dest, const char* orig, int nlength, int tpos, bool align_right);
void TruncateString(char* dest, const char* orig, int nlength, int tpos);
void FormatNumber(char* str, u64 number);
void FormatBytes(char* str, u64 bytes);
void FormatBytes(char* str, u64 bytes, bool useLocale);
void PRINTF_ARGS(1) ShowString(const char *format, ...);
void PRINTF_ARGS(2) ShowStringF(u16* screen, const char *format, ...);

View File

@ -755,8 +755,8 @@ bool PathCopy(const char* destdir, const char* orig, u32* flags) {
char dsizestr[32];
TruncateString(deststr, dest, 36, 8);
TruncateString(origstr, orig, 36, 8);
FormatBytes(osizestr, osize);
FormatBytes(dsizestr, dvfile.size);
FormatBytes(osizestr, osize, true);
FormatBytes(dsizestr, dvfile.size, true);
if (dvfile.size > osize) {
if (!ShowPrompt(true, STR_FILE_SMALLER_THAN_SPACE_SIZES_CONTINUE, origstr, osizestr, deststr, dsizestr))
return false;

View File

@ -252,8 +252,8 @@ void DrawTopBar(const char* curr_path) {
char tempstr[UTF_BUFFER_BYTESIZE(19)];
ResizeString(tempstr, STR_LOADING, 19, 19, true);
DrawString(TOP_SCREEN, tempstr, bartxt_rx, bartxt_start, COLOR_STD_BG, COLOR_TOP_BAR);
FormatBytes(bytestr0, GetFreeSpace(curr_path));
FormatBytes(bytestr1, GetTotalSpace(curr_path));
FormatBytes(bytestr0, GetFreeSpace(curr_path), true);
FormatBytes(bytestr1, GetTotalSpace(curr_path), true);
snprintf(tempstr, sizeof(tempstr), "%s/%s", bytestr0, bytestr1);
DrawStringF(TOP_SCREEN, bartxt_rx, bartxt_start, COLOR_STD_BG, COLOR_TOP_BAR, "%19.19s", tempstr);
show_time = false;
@ -262,7 +262,7 @@ void DrawTopBar(const char* curr_path) {
if (true) { // allocated mem
const u32 bartxt_rx = SCREEN_WIDTH_TOP - (9*FONT_WIDTH_EXT) - bartxt_x;
char bytestr[32];
FormatBytes(bytestr, mem_allocated());
FormatBytes(bytestr, mem_allocated(), true);
DrawStringF(TOP_SCREEN, bartxt_rx, bartxt_start, COLOR_STD_BG, COLOR_TOP_BAR, "%9.9s", bytestr);
show_time = false;
}
@ -399,7 +399,7 @@ void DrawDirContents(DirStruct* contents, u32 cursor, u32* scroll) {
char namestr[UTF_BUFFER_BYTESIZE(str_width - 10)];
char rawbytestr[32], bytestr[UTF_BUFFER_BYTESIZE(10)];
color_font = (cursor != offset_i) ? COLOR_ENTRY(curr_entry) : COLOR_STD_FONT;
FormatBytes(rawbytestr, curr_entry->size);
FormatBytes(rawbytestr, curr_entry->size, true);
ResizeString(bytestr, (curr_entry->type == T_DIR) ? STR_DIR : (curr_entry->type == T_DOTDOT) ? "(..)" : rawbytestr, 10, 10, true);
ResizeString(namestr, curr_entry->name, str_width - 10, str_width - 20, false);
snprintf(tempstr, sizeof(tempstr), "%s%s", namestr, bytestr);
@ -1031,7 +1031,7 @@ u32 CartRawDump(void) {
// input dump size
dsize = cdata->cart_size;
FormatBytes(bytestr, dsize);
FormatBytes(bytestr, dsize, true);
dsize = ShowHexPrompt(dsize, 8, STR_CART_DETECTED_SIZE_INPUT_BELOW, cname, bytestr);
if (!dsize || (dsize == (u64) -1)) {
free(cdata);
@ -1113,13 +1113,13 @@ u32 DirFileAttrMenu(const char* path, const char *name) {
ShowString("%s", drv ? STR_ANALYZING_DRIVE : STR_ANALYZING_DIR);
if (!DirInfo(path, &tsize, &tdirs, &tfiles))
return 1;
FormatBytes(bytestr, tsize);
FormatBytes(bytestr, tsize, true);
if (drv) { // drive specific
char freestr[32], drvsstr[32], usedstr[32];
FormatBytes(freestr, GetFreeSpace(path));
FormatBytes(drvsstr, GetTotalSpace(path));
FormatBytes(usedstr, GetTotalSpace(path) - GetFreeSpace(path));
FormatBytes(freestr, GetFreeSpace(path), true);
FormatBytes(drvsstr, GetTotalSpace(path), true);
FormatBytes(usedstr, GetTotalSpace(path) - GetFreeSpace(path), true);
snprintf(sizestr, sizeof(sizestr), STR_N_FILES_N_SUBDIRS_TOTAL_SIZE_FREE_USED_TOTAL,
tfiles, tdirs, bytestr, freestr, usedstr, drvsstr);
} else { // dir specific
@ -1127,7 +1127,7 @@ u32 DirFileAttrMenu(const char* path, const char *name) {
}
} else { // for files
char bytestr[32];
FormatBytes(bytestr, fno.fsize);
FormatBytes(bytestr, fno.fsize, true);
snprintf(sizestr, sizeof(sizestr), STR_FILESIZE_X, bytestr);
}
@ -2018,7 +2018,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
}
current_dir->entry[i].marked = false;
}
FormatBytes(savingsstr, savings);
FormatBytes(savingsstr, savings, true);
if (n_other) ShowPrompt(false, STR_N_OF_N_FILES_TRIMMED_N_OF_N_NOT_OF_SAME_TYPE_X_SAVED,
n_success, n_marked, n_other, n_marked, savingsstr);
else ShowPrompt(false, STR_N_OF_N_FILES_TRIMMED_X_SAVED, n_success, n_marked, savingsstr);
@ -2029,9 +2029,9 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
char tsizestr[32];
char csizestr[32];
char dsizestr[32];
FormatBytes(tsizestr, trimsize);
FormatBytes(csizestr, currentsize);
FormatBytes(dsizestr, currentsize - trimsize);
FormatBytes(tsizestr, trimsize, true);
FormatBytes(csizestr, currentsize, true);
FormatBytes(dsizestr, currentsize - trimsize, true);
if (!trimsize || trimsize > currentsize) {
ShowPrompt(false, "%s\n%s", pathstr, STR_FILE_CANT_BE_TRIMMED);

View File

@ -14,10 +14,11 @@
#define EXPLORER (1UL<<16)
#define ENCRYPTED (1UL<<17)
#define SIG_CHECK (1UL<<18)
#define USE_LOCALE (1UL<<19)
#define FLAGS_STR "no_cancel", "silent", "calc_sha", "sha1", "skip", "overwrite", "append", "all", "recursive", "to_emunand", "legit", "first", "include_dirs", "explorer", "encrypted", "sig_check"
#define FLAGS_CONSTS NO_CANCEL, SILENT, CALC_SHA, USE_SHA1, SKIP_ALL, OVERWRITE_ALL, APPEND_ALL, ASK_ALL, RECURSIVE, TO_EMUNAND, LEGIT, FIND_FIRST, INCLUDE_DIRS, EXPLORER, ENCRYPTED, SIG_CHECK
#define FLAGS_COUNT 16
#define FLAGS_STR "no_cancel", "silent", "calc_sha", "sha1", "skip", "overwrite", "append", "all", "recursive", "to_emunand", "legit", "first", "include_dirs", "explorer", "encrypted", "sig_check", "use_locale"
#define FLAGS_CONSTS NO_CANCEL, SILENT, CALC_SHA, USE_SHA1, SKIP_ALL, OVERWRITE_ALL, APPEND_ALL, ASK_ALL, RECURSIVE, TO_EMUNAND, LEGIT, FIND_FIRST, INCLUDE_DIRS, EXPLORER, ENCRYPTED, SIG_CHECK, USE_LOCALE
#define FLAGS_COUNT 17
#define LUASCRIPT_EXT "lua"
#define LUASCRIPT_MAX_SIZE STD_BUFFER_SIZE

View File

@ -284,11 +284,16 @@ static int ui_ask_selection(lua_State* L) {
}
static int ui_format_bytes(lua_State* L) {
CheckLuaArgCount(L, 1, "ui.format_bytes");
bool extra = CheckLuaArgCountPlusExtra(L, 1, "ui.format_bytes");
lua_Integer size = luaL_checkinteger(L, 1);
u32 flags = 0;
if (extra) {
flags = GetFlagsFromTable(L, 2, flags, USE_LOCALE);
}
char bytesstr[32] = { 0 };
FormatBytes(bytesstr, (u64)size);
FormatBytes(bytesstr, (u64)size, flags & USE_LOCALE);
lua_pushstring(L, bytesstr);
return 1;

View File

@ -3578,7 +3578,7 @@ u32 ShowGameCheckerInfo(const char* path) {
for (u32 i = 0; i < content_count; i++, chunk++)
content_size += getbe64(chunk->size);
}
FormatBytes(bytestr, content_size);
FormatBytes(bytestr, content_size, true);
// check ticket
if (ticket && ValidateTicket(ticket) == 0)

View File

@ -453,7 +453,7 @@ void upd_var(const char* name) {
if (!name || (strncmp(name, "SDSIZE", _VAR_NAME_LEN) == 0)) {
u64 sdsize = GetTotalSpace("0:");
char sdsize_str[32+1];
FormatBytes(sdsize_str, sdsize);
FormatBytes(sdsize_str, sdsize, false);
set_var("SDSIZE", sdsize_str);
}
@ -461,7 +461,7 @@ void upd_var(const char* name) {
if (!name || (strncmp(name, "SDFREE", _VAR_NAME_LEN) == 0)) {
u64 sdfree = GetFreeSpace("0:");
char sdfree_str[32+1];
FormatBytes(sdfree_str, sdfree);
FormatBytes(sdfree_str, sdfree, false);
set_var("SDFREE", sdfree_str);
}
@ -469,7 +469,7 @@ void upd_var(const char* name) {
if (!name || (strncmp(name, "NANDSIZE", _VAR_NAME_LEN) == 0)) {
u64 nandsize = GetNandSizeSectors(NAND_SYSNAND) * 0x200;
char nandsize_str[32+1];
FormatBytes(nandsize_str, nandsize);
FormatBytes(nandsize_str, nandsize, false);
set_var("NANDSIZE", nandsize_str);
}
}

View File

@ -340,15 +340,14 @@ Display a scrollable text viewer from a text file.
#### ui.format_bytes
* `string ui.format_bytes(int bytes)`
* `string ui.format_bytes(int bytes[, table opts {bool use_locale}])`
Format a number with `Byte`, `kB`, `MB`, or `GB`.
> [!NOTE]
> This is affected by localization and may return different text if the language is not English.
Format a number with `Byte`, `kB`, `MB`, or `GB`. By default this will always use English style formatting. Enable `use_locale` to format in the user's selected language.
* **Arguments**
* `bytes` - Size to format
* `opts` (optional) - Option flags
* `use_locale` - Format in the user's selected locale
* **Returns:** formatted string
#### ui.check_key