xref: /haiku/src/kits/shared/StringForSize.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 	BString printedSize;
32 
33 	double value = size / 1024.0;
34 	if (value < 1024.0) {
35 		BStringFormat format(
36 			B_TRANSLATE_MARK_ALL("{0, plural, one{# byte} other{# bytes}}",
37 			B_TRANSLATION_CONTEXT, "size unit"));
38 
39 		format.Format(printedSize, (int)size);
40 		strlcpy(string, gSystemCatalog.GetString(printedSize.String(), B_TRANSLATION_CONTEXT,
41 			"size unit"), stringSize);
42 
43 		return string;
44 	}
45 
46 	const char* kFormats[] = {
47 		B_TRANSLATE_MARK_ALL("%s KiB", B_TRANSLATION_CONTEXT, "size unit"),
48 		B_TRANSLATE_MARK_ALL("%s MiB", B_TRANSLATION_CONTEXT, "size unit"),
49 		B_TRANSLATE_MARK_ALL("%s GiB", B_TRANSLATION_CONTEXT, "size unit"),
50 		B_TRANSLATE_MARK_ALL("%s TiB", B_TRANSLATION_CONTEXT, "size unit")
51 	};
52 
53 	size_t index = 0;
54 	while (index < B_COUNT_OF(kFormats) && value >= 1024.0) {
55 		value /= 1024.0;
56 		index++;
57 	}
58 
59 	BNumberFormat numberFormat;
60 	numberFormat.SetPrecision(2);
61 	numberFormat.Format(printedSize, value);
62 	snprintf(string, stringSize, gSystemCatalog.GetString(kFormats[index], B_TRANSLATION_CONTEXT,
63 		"size unit"), printedSize.String());
64 
65 	return string;
66 }
67 
68 
69 int64
70 parse_size(const char* sizeString)
71 {
72 	int64 parsedSize = -1;
73 	char* end;
74 	parsedSize = strtoll(sizeString, &end, 0);
75 	if (end != sizeString && parsedSize > 0) {
76 		int64 rawSize = parsedSize;
77 		switch (tolower(*end)) {
78 			case 't':
79 				parsedSize *= 1024;
80 			case 'g':
81 				parsedSize *= 1024;
82 			case 'm':
83 				parsedSize *= 1024;
84 			case 'k':
85 				parsedSize *= 1024;
86 				end++;
87 				break;
88 			case '\0':
89 				break;
90 			default:
91 				parsedSize = -1;
92 				break;
93 		}
94 
95 		// Check for overflow
96 		if (parsedSize > 0 && rawSize > parsedSize)
97 			parsedSize = -1;
98 	}
99 
100 	return parsedSize;
101 }
102 
103 
104 }	// namespace BPrivate
105 
106