xref: /haiku/src/kits/shared/StringForSize.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2  * Copyright 2010-2024 Haiku Inc. All rights reserved.
3  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 #include "StringForSize.h"
8 
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 
13 #include <NumberFormat.h>
14 #include <StringFormat.h>
15 #include <SystemCatalog.h>
16 
17 
18 using BPrivate::gSystemCatalog;
19 
20 
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "StringForSize"
23 
24 
25 namespace BPrivate {
26 
27 
28 const char*
29 string_for_size(double size, char* string, size_t stringSize)
30 {
31 	const char* kFormats[] = {
32 		B_TRANSLATE_MARK_COMMENT("{0, plural, one{%s byte} other{%s bytes}}", "size unit"),
33 		B_TRANSLATE_MARK_COMMENT("%s KiB", "size unit"),
34 		B_TRANSLATE_MARK_COMMENT("%s MiB", "size unit"),
35 		B_TRANSLATE_MARK_COMMENT("%s GiB", "size unit"),
36 		B_TRANSLATE_MARK_COMMENT("%s TiB", "size unit")
37 	};
38 
39 	size_t index = 0;
40 	while (index < B_COUNT_OF(kFormats) - 1 && size >= 1024.0) {
41 		size /= 1024.0;
42 		index++;
43 	}
44 
45 	BString format;
46 	BStringFormat formatter(
47 		gSystemCatalog.GetString(kFormats[index], B_TRANSLATION_CONTEXT, "size unit"));
48 	formatter.Format(format, size);
49 
50 	BString printedSize;
51 	BNumberFormat numberFormat;
52 	numberFormat.SetPrecision(index == 0 ? 0 : 2);
53 	numberFormat.Format(printedSize, size);
54 
55 	snprintf(string, stringSize, format.String(), printedSize.String());
56 
57 	return string;
58 }
59 
60 
61 int64
62 parse_size(const char* sizeString)
63 {
64 	int64 parsedSize = -1;
65 	char* end;
66 	parsedSize = strtoll(sizeString, &end, 0);
67 	if (end != sizeString && parsedSize > 0) {
68 		int64 rawSize = parsedSize;
69 		switch (tolower(*end)) {
70 			case 't':
71 				parsedSize *= 1024;
72 			case 'g':
73 				parsedSize *= 1024;
74 			case 'm':
75 				parsedSize *= 1024;
76 			case 'k':
77 				parsedSize *= 1024;
78 				end++;
79 				break;
80 			case '\0':
81 				break;
82 			default:
83 				parsedSize = -1;
84 				break;
85 		}
86 
87 		// Check for overflow
88 		if (parsedSize > 0 && rawSize > parsedSize)
89 			parsedSize = -1;
90 	}
91 
92 	return parsedSize;
93 }
94 
95 
96 }	// namespace BPrivate
97 
98