Line data Source code
1 : /**
2 : * @file human_size.c
3 : * @brief Implementation of human-readable size parsing and formatting.
4 : * @ingroup Utilities
5 : */
6 : #include "human_size.h"
7 : #include <ctype.h>
8 : #include <stdio.h>
9 : #include <stdlib.h>
10 : #include <string.h>
11 : #include <apr_strings.h>
12 :
13 8 : const char *format_human_size(apr_off_t size, apr_pool_t *pool)
14 : {
15 8 : const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" };
16 8 : int i = 0;
17 8 : double readable_size = (double) size;
18 :
19 19 : while (readable_size >= 1024.0 && i < (sizeof(units) / sizeof(units[0]) - 1)) {
20 11 : readable_size /= 1024.0;
21 11 : i++;
22 : }
23 :
24 8 : if (i == 0) {
25 3 : return apr_psprintf(pool, "%d %s", (int) readable_size, units[i]);
26 : }
27 : else {
28 5 : return apr_psprintf(pool, "%.1f %s", readable_size, units[i]);
29 : }
30 : }
31 :
32 17 : apr_off_t parse_human_size(const char *size_str)
33 : {
34 : char *endptr;
35 17 : double size = strtod(size_str, &endptr);
36 17 : apr_off_t multiplier = 1;
37 :
38 17 : if (endptr == size_str) {
39 2 : return -1; // Not a valid number
40 : }
41 :
42 15 : while (*endptr && isspace((unsigned char) *endptr)) {
43 0 : endptr++;
44 : }
45 :
46 15 : if (*endptr) {
47 14 : switch (toupper((unsigned char) *endptr)) {
48 2 : case 'T':
49 2 : multiplier = 1024LL * 1024LL * 1024LL * 1024LL;
50 2 : break;
51 2 : case 'G':
52 2 : multiplier = 1024LL * 1024LL * 1024LL;
53 2 : break;
54 3 : case 'M':
55 3 : multiplier = 1024LL * 1024LL;
56 3 : break;
57 5 : case 'K':
58 5 : multiplier = 1024LL;
59 5 : break;
60 2 : default:
61 2 : return -1; // Invalid suffix
62 : }
63 : }
64 :
65 13 : return (apr_off_t) (size * multiplier);
66 : }
|