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	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
69int64
70parse_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