Skip to content

Commit baa9133

Browse files
committed
lib/compat/humanize_number.c: switch to freebsd version
1 parent 48c3a82 commit baa9133

File tree

2 files changed

+101
-57
lines changed

2 files changed

+101
-57
lines changed

include/compat.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@ int HIDDEN vasprintf(char **, const char *, va_list);
2828
#endif
2929

3030
#ifndef HAVE_HUMANIZE_NUMBER
31-
#define HN_DECIMAL 0x01
32-
#define HN_NOSPACE 0x02
33-
#define HN_B 0x04
34-
#define HN_DIVISOR_1000 0x08
35-
#define HN_GETSCALE 0x10
36-
#define HN_AUTOSCALE 0x20
37-
int HIDDEN humanize_number(char *, size_t, int64_t, const char *, int, int);
31+
/* Values for humanize_number(3)'s flags parameter. */
32+
#define HN_DECIMAL 0x01
33+
#define HN_NOSPACE 0x02
34+
#define HN_B 0x04
35+
#define HN_DIVISOR_1000 0x08
36+
#define HN_IEC_PREFIXES 0x10
37+
38+
/* Values for humanize_number(3)'s scale parameter. */
39+
#define HN_GETSCALE 0x10
40+
#define HN_AUTOSCALE 0x20
41+
42+
int HIDDEN humanize_number(char *_buf, size_t _len, int64_t _number,
43+
const char *_suffix, int _scale, int _flags);
3844
#endif
3945

4046
#endif /* COMPAT_H */

lib/compat/humanize_number.c

Lines changed: 88 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
/* $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $ */
22

3-
/*
3+
/*-
4+
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5+
*
46
* Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
7+
* Copyright 2013 John-Mark Gurney <jmg@FreeBSD.org>
58
* All rights reserved.
69
*
710
* This code is derived from software contributed to The NetBSD Foundation
@@ -30,68 +33,93 @@
3033
* POSSIBILITY OF SUCH DAMAGE.
3134
*/
3235

36+
#include <sys/types.h>
3337
#include <assert.h>
3438
#include <inttypes.h>
3539
#include <stdio.h>
3640
#include <stdlib.h>
3741
#include <string.h>
3842
#include <locale.h>
3943

40-
#include "xbps_api_impl.h"
4144
#include "compat.h"
4245

46+
47+
static const int maxscale = 6;
48+
49+
4350
int HIDDEN
44-
humanize_number(char *buf, size_t len, int64_t bytes,
45-
const char *suffix, int scale, int flags)
51+
humanize_number(char *buf, size_t len, int64_t quotient,
52+
const char *suffix, int scale, int flags)
4653
{
4754
const char *prefixes, *sep;
48-
int b, i, r, maxscale, s1, s2, sign;
55+
int i, r, remainder, s1, s2, sign;
56+
int divisordeccut;
4957
int64_t divisor, max;
5058
size_t baselen;
5159

52-
assert(buf != NULL);
53-
assert(suffix != NULL);
54-
assert(scale >= 0);
60+
/* Since so many callers don't check -1, NUL terminate the buffer */
61+
if (len > 0)
62+
buf[0] = '\0';
5563

56-
if (flags & HN_DIVISOR_1000) {
57-
/* SI for decimal multiplies */
58-
divisor = 1000;
59-
if (flags & HN_B)
60-
prefixes = "B\0k\0M\0G\0T\0P\0E";
61-
else
62-
prefixes = "\0\0k\0M\0G\0T\0P\0E";
63-
} else {
64+
/* validate args */
65+
if (buf == NULL || suffix == NULL)
66+
return (-1);
67+
if (scale < 0)
68+
return (-1);
69+
else if (scale > maxscale &&
70+
((scale & ~(HN_AUTOSCALE|HN_GETSCALE)) != 0))
71+
return (-1);
72+
if ((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))
73+
return (-1);
74+
75+
/* setup parameters */
76+
remainder = 0;
77+
78+
if (flags & HN_IEC_PREFIXES) {
79+
baselen = 2;
6480
/*
65-
* binary multiplies
66-
* XXX IEC 60027-2 recommends Ki, Mi, Gi...
81+
* Use the prefixes for power of two recommended by
82+
* the International Electrotechnical Commission
83+
* (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
84+
*
85+
* HN_IEC_PREFIXES implies a divisor of 1024 here
86+
* (use of HN_DIVISOR_1000 would have triggered
87+
* an assertion earlier).
6788
*/
6889
divisor = 1024;
90+
divisordeccut = 973; /* ceil(.95 * 1024) */
6991
if (flags & HN_B)
70-
prefixes = "B\0K\0M\0G\0T\0P\0E";
92+
prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
7193
else
72-
prefixes = "\0\0K\0M\0G\0T\0P\0E";
94+
prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
95+
} else {
96+
baselen = 1;
97+
if (flags & HN_DIVISOR_1000) {
98+
divisor = 1000;
99+
divisordeccut = 950;
100+
if (flags & HN_B)
101+
prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
102+
else
103+
prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
104+
} else {
105+
divisor = 1024;
106+
divisordeccut = 973; /* ceil(.95 * 1024) */
107+
if (flags & HN_B)
108+
prefixes = "B\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
109+
else
110+
prefixes = "\0\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
111+
}
73112
}
74113

75-
#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1])
76-
maxscale = 7;
114+
#define SCALE2PREFIX(scale) (&prefixes[(scale) * 3])
77115

78-
if (scale >= maxscale &&
79-
(scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
80-
return (-1);
81-
82-
if (buf == NULL || suffix == NULL)
83-
return (-1);
84-
85-
if (len > 0)
86-
buf[0] = '\0';
87-
if (bytes < 0) {
116+
if (quotient < 0) {
88117
sign = -1;
89-
bytes *= -100;
90-
baselen = 3; /* sign, digit, prefix */
118+
quotient = -quotient;
119+
baselen += 2; /* sign, digit */
91120
} else {
92121
sign = 1;
93-
bytes *= 100;
94-
baselen = 2; /* digit, prefix */
122+
baselen += 1; /* digit */
95123
}
96124
if (flags & HN_NOSPACE)
97125
sep = "";
@@ -107,37 +135,47 @@ humanize_number(char *buf, size_t len, int64_t bytes,
107135

108136
if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
109137
/* See if there is additional columns can be used. */
110-
for (max = 100, i = (int)(len - baselen); i-- > 0;)
138+
for (max = 1, i = len - baselen; i-- > 0;)
111139
max *= 10;
112140

113141
/*
114142
* Divide the number until it fits the given column.
115143
* If there will be an overflow by the rounding below,
116144
* divide once more.
117145
*/
118-
for (i = 0; bytes >= max - 50 && i < maxscale; i++)
119-
bytes /= divisor;
146+
for (i = 0;
147+
(quotient >= max || (quotient == max - 1 &&
148+
(remainder >= divisordeccut || remainder >=
149+
divisor / 2))) && i < maxscale; i++) {
150+
remainder = quotient % divisor;
151+
quotient /= divisor;
152+
}
120153

121154
if (scale & HN_GETSCALE)
122155
return (i);
123-
} else
124-
for (i = 0; i < scale && i < maxscale; i++)
125-
bytes /= divisor;
156+
} else {
157+
for (i = 0; i < scale && i < maxscale; i++) {
158+
remainder = quotient % divisor;
159+
quotient /= divisor;
160+
}
161+
}
126162

127163
/* If a value <= 9.9 after rounding and ... */
128-
if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
129-
/* baselen + \0 + .N */
130-
if (len < baselen + 1 + 2)
131-
return (-1);
132-
b = ((int)bytes + 5) / 10;
133-
s1 = b / 10;
134-
s2 = b % 10;
164+
/*
165+
* XXX - should we make sure there is enough space for the decimal
166+
* place and if not, don't do HN_DECIMAL?
167+
*/
168+
if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) &&
169+
i > 0 && flags & HN_DECIMAL) {
170+
s1 = (int)quotient + ((remainder * 10 + divisor / 2) /
171+
divisor / 10);
172+
s2 = ((remainder * 10 + divisor / 2) / divisor) % 10;
135173
r = snprintf(buf, len, "%d%s%d%s%s%s",
136174
sign * s1, localeconv()->decimal_point, s2,
137175
sep, SCALE2PREFIX(i), suffix);
138176
} else
139177
r = snprintf(buf, len, "%" PRId64 "%s%s%s",
140-
sign * ((bytes + 50) / 100),
178+
sign * (quotient + (remainder + divisor / 2) / divisor),
141179
sep, SCALE2PREFIX(i), suffix);
142180

143181
return (r);

0 commit comments

Comments
 (0)