xref: /netbsd-src/usr.bin/systat/convtbl.c (revision 6f3aa0fcd4cc9336c21474843309b50b958223b1)
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