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
18using BPrivate::gSystemCatalog;
19
20
21#undef B_TRANSLATION_CONTEXT
22#define B_TRANSLATION_CONTEXT "StringForSize"
23
24
25namespace BPrivate {
26
27
28const char*
29string_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
61int64
62parse_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