1*6f3aa0fcSscole /* $NetBSD: convtbl.c,v 1.2 2016/08/02 17:53:46 scole Exp $ */
2*6f3aa0fcSscole
3bd7662dcSscole /*
4bd7662dcSscole * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
5bd7662dcSscole * All rights reserved.
6bd7662dcSscole *
7bd7662dcSscole * Redistribution and use in source and binary forms, with or without
8bd7662dcSscole * modification, are permitted provided that the following conditions
9bd7662dcSscole * are met:
10bd7662dcSscole * 1. Redistributions of source code must retain the above copyright
11bd7662dcSscole * notice, this list of conditions and the following disclaimer.
12bd7662dcSscole * 2. Redistributions in binary form must reproduce the above copyright
13bd7662dcSscole * notice, this list of conditions and the following disclaimer in the
14bd7662dcSscole * documentation and/or other materials provided with the distribution.
15bd7662dcSscole * 3. The name of the author may not be used to endorse or promote products
16bd7662dcSscole * derived from this software without specific prior written permission.
17bd7662dcSscole *
18bd7662dcSscole * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19bd7662dcSscole * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20bd7662dcSscole * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21bd7662dcSscole * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22bd7662dcSscole * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23bd7662dcSscole * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24bd7662dcSscole * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25bd7662dcSscole * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26bd7662dcSscole * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27bd7662dcSscole * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28bd7662dcSscole * SUCH DAMAGE.
29bd7662dcSscole *
30bd7662dcSscole * $FreeBSD: releng/10.1/usr.bin/systat/convtbl.c 175387 2008-01-16 19:27:43Z delphij $
31bd7662dcSscole */
32bd7662dcSscole
33bd7662dcSscole #include <sys/cdefs.h>
34bd7662dcSscole #ifndef lint
35*6f3aa0fcSscole __RCSID("$NetBSD: convtbl.c,v 1.2 2016/08/02 17:53:46 scole Exp $");
36bd7662dcSscole #endif /* not lint */
37bd7662dcSscole
38bd7662dcSscole #include <sys/types.h>
39bd7662dcSscole
40bd7662dcSscole #include <stdlib.h>
41bd7662dcSscole #include <string.h>
42bd7662dcSscole
43bd7662dcSscole #include "convtbl.h"
44bd7662dcSscole
45bd7662dcSscole #define BIT (8)
46bd7662dcSscole #define BITS (1)
47bd7662dcSscole #define KILOBIT (1000LL)
48bd7662dcSscole #define MEGABIT (KILOBIT * 1000)
49bd7662dcSscole #define GIGABIT (MEGABIT * 1000)
50bd7662dcSscole #define TERABIT (GIGABIT * 1000)
51bd7662dcSscole
52bd7662dcSscole #define BYTE (1)
53bd7662dcSscole #define BYTES (1)
54bd7662dcSscole #define KILOBYTE (1024LL)
55bd7662dcSscole #define MEGABYTE (KILOBYTE * 1024)
56bd7662dcSscole #define GIGABYTE (MEGABYTE * 1024)
57bd7662dcSscole #define TERABYTE (GIGABYTE * 1024)
58bd7662dcSscole
59bd7662dcSscole struct convtbl {
60bd7662dcSscole uintmax_t mul;
61bd7662dcSscole uintmax_t scale;
62bd7662dcSscole const char *str;
63bd7662dcSscole const char *name;
64bd7662dcSscole };
65bd7662dcSscole
66bd7662dcSscole static struct convtbl convtbl[] = {
67bd7662dcSscole /* mul, scale, str, name */
68bd7662dcSscole [SC_BYTE] = { BYTE, BYTES, "B", "byte" },
69bd7662dcSscole [SC_KILOBYTE] = { BYTE, KILOBYTE, "KB", "kbyte" },
70bd7662dcSscole [SC_MEGABYTE] = { BYTE, MEGABYTE, "MB", "mbyte" },
71bd7662dcSscole [SC_GIGABYTE] = { BYTE, GIGABYTE, "GB", "gbyte" },
72bd7662dcSscole [SC_TERABYTE] = { BYTE, TERABYTE, "TB", "tbyte" },
73bd7662dcSscole
74bd7662dcSscole [SC_BIT] = { BIT, BITS, "b", "bit" },
75bd7662dcSscole [SC_KILOBIT] = { BIT, KILOBIT, "Kb", "kbit" },
76bd7662dcSscole [SC_MEGABIT] = { BIT, MEGABIT, "Mb", "mbit" },
77bd7662dcSscole [SC_GIGABIT] = { BIT, GIGABIT, "Gb", "gbit" },
78bd7662dcSscole [SC_TERABIT] = { BIT, TERABIT, "Tb", "tbit" },
79bd7662dcSscole
80bd7662dcSscole [SC_AUTO] = { 0, 0, "", "auto" }
81bd7662dcSscole };
82bd7662dcSscole
83bd7662dcSscole static
84bd7662dcSscole struct convtbl *
get_tbl_ptr(const uintmax_t size,const int scale)85bd7662dcSscole get_tbl_ptr(const uintmax_t size, const int scale)
86bd7662dcSscole {
87bd7662dcSscole uintmax_t tmp;
88bd7662dcSscole int idx;
89bd7662dcSscole
90bd7662dcSscole /* If our index is out of range, default to auto-scaling. */
91bd7662dcSscole idx = scale < SC_AUTO ? scale : SC_AUTO;
92bd7662dcSscole
93bd7662dcSscole if (idx == SC_AUTO)
94bd7662dcSscole /*
95bd7662dcSscole * Simple but elegant algorithm. Count how many times
96bd7662dcSscole * we can shift our size value right by a factor of ten,
97bd7662dcSscole * incrementing an index each time. We then use the
98bd7662dcSscole * index as the array index into the conversion table.
99bd7662dcSscole */
100bd7662dcSscole for (tmp = size, idx = SC_KILOBYTE;
101bd7662dcSscole tmp >= MEGABYTE && idx < SC_BIT - 1;
102bd7662dcSscole tmp >>= 10, idx++);
103bd7662dcSscole
104bd7662dcSscole return (&convtbl[idx]);
105bd7662dcSscole }
106bd7662dcSscole
107bd7662dcSscole double
convert(const uintmax_t size,const int scale)108bd7662dcSscole convert(const uintmax_t size, const int scale)
109bd7662dcSscole {
110bd7662dcSscole struct convtbl *tp;
111bd7662dcSscole
112bd7662dcSscole tp = get_tbl_ptr(size, scale);
113bd7662dcSscole return ((double)size * tp->mul / tp->scale);
114bd7662dcSscole
115bd7662dcSscole }
116bd7662dcSscole
117bd7662dcSscole const char *
get_string(const uintmax_t size,const int scale)118bd7662dcSscole get_string(const uintmax_t size, const int scale)
119bd7662dcSscole {
120bd7662dcSscole struct convtbl *tp;
121bd7662dcSscole
122bd7662dcSscole tp = get_tbl_ptr(size, scale);
123bd7662dcSscole return (tp->str);
124bd7662dcSscole }
125bd7662dcSscole
126bd7662dcSscole int
get_scale(const char * name)127bd7662dcSscole get_scale(const char *name)
128bd7662dcSscole {
129bd7662dcSscole int i;
130bd7662dcSscole
131bd7662dcSscole for (i = 0; i <= SC_AUTO; i++)
132bd7662dcSscole if (strcmp(convtbl[i].name, name) == 0)
133bd7662dcSscole return (i);
134bd7662dcSscole return (-1);
135bd7662dcSscole }
136bd7662dcSscole
137bd7662dcSscole const char *
get_helplist(void)138bd7662dcSscole get_helplist(void)
139bd7662dcSscole {
140bd7662dcSscole int i;
141bd7662dcSscole size_t len;
142bd7662dcSscole static char *buf;
143bd7662dcSscole
144bd7662dcSscole if (buf == NULL) {
145bd7662dcSscole len = 0;
146bd7662dcSscole for (i = 0; i <= SC_AUTO; i++)
147bd7662dcSscole len += strlen(convtbl[i].name) + 2;
148bd7662dcSscole if ((buf = malloc(len)) != NULL) {
149bd7662dcSscole buf[0] = '\0';
150bd7662dcSscole for (i = 0; i <= SC_AUTO; i++) {
151bd7662dcSscole strcat(buf, convtbl[i].name);
152bd7662dcSscole if (i < SC_AUTO)
153bd7662dcSscole strcat(buf, ", ");
154bd7662dcSscole }
155bd7662dcSscole } else
156bd7662dcSscole return ("");
157bd7662dcSscole }
158bd7662dcSscole return (buf);
159bd7662dcSscole }
160