xref: /linux/tools/perf/util/units.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
258db1d6eSArnaldo Carvalho de Melo #include "units.h"
358db1d6eSArnaldo Carvalho de Melo #include <inttypes.h>
43caeafceSArnaldo Carvalho de Melo #include <limits.h>
53caeafceSArnaldo Carvalho de Melo #include <stdlib.h>
63caeafceSArnaldo Carvalho de Melo #include <string.h>
758db1d6eSArnaldo Carvalho de Melo #include <linux/kernel.h>
858db1d6eSArnaldo Carvalho de Melo #include <linux/time64.h>
958db1d6eSArnaldo Carvalho de Melo 
parse_tag_value(const char * str,struct parse_tag * tags)103caeafceSArnaldo Carvalho de Melo unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
113caeafceSArnaldo Carvalho de Melo {
123caeafceSArnaldo Carvalho de Melo 	struct parse_tag *i = tags;
133caeafceSArnaldo Carvalho de Melo 
143caeafceSArnaldo Carvalho de Melo 	while (i->tag) {
153caeafceSArnaldo Carvalho de Melo 		char *s = strchr(str, i->tag);
163caeafceSArnaldo Carvalho de Melo 
173caeafceSArnaldo Carvalho de Melo 		if (s) {
183caeafceSArnaldo Carvalho de Melo 			unsigned long int value;
193caeafceSArnaldo Carvalho de Melo 			char *endptr;
203caeafceSArnaldo Carvalho de Melo 
213caeafceSArnaldo Carvalho de Melo 			value = strtoul(str, &endptr, 10);
223caeafceSArnaldo Carvalho de Melo 			if (s != endptr)
233caeafceSArnaldo Carvalho de Melo 				break;
243caeafceSArnaldo Carvalho de Melo 
253caeafceSArnaldo Carvalho de Melo 			if (value > ULONG_MAX / i->mult)
263caeafceSArnaldo Carvalho de Melo 				break;
273caeafceSArnaldo Carvalho de Melo 			value *= i->mult;
283caeafceSArnaldo Carvalho de Melo 			return value;
293caeafceSArnaldo Carvalho de Melo 		}
303caeafceSArnaldo Carvalho de Melo 		i++;
313caeafceSArnaldo Carvalho de Melo 	}
323caeafceSArnaldo Carvalho de Melo 
333caeafceSArnaldo Carvalho de Melo 	return (unsigned long) -1;
343caeafceSArnaldo Carvalho de Melo }
353caeafceSArnaldo Carvalho de Melo 
convert_unit_double(double value,char * unit)36*6859bc0eSChangbin Du double convert_unit_double(double value, char *unit)
3758db1d6eSArnaldo Carvalho de Melo {
3858db1d6eSArnaldo Carvalho de Melo 	*unit = ' ';
3958db1d6eSArnaldo Carvalho de Melo 
40*6859bc0eSChangbin Du 	if (value > 1000.0) {
41*6859bc0eSChangbin Du 		value /= 1000.0;
4258db1d6eSArnaldo Carvalho de Melo 		*unit = 'K';
4358db1d6eSArnaldo Carvalho de Melo 	}
4458db1d6eSArnaldo Carvalho de Melo 
45*6859bc0eSChangbin Du 	if (value > 1000.0) {
46*6859bc0eSChangbin Du 		value /= 1000.0;
4758db1d6eSArnaldo Carvalho de Melo 		*unit = 'M';
4858db1d6eSArnaldo Carvalho de Melo 	}
4958db1d6eSArnaldo Carvalho de Melo 
50*6859bc0eSChangbin Du 	if (value > 1000.0) {
51*6859bc0eSChangbin Du 		value /= 1000.0;
5258db1d6eSArnaldo Carvalho de Melo 		*unit = 'G';
5358db1d6eSArnaldo Carvalho de Melo 	}
5458db1d6eSArnaldo Carvalho de Melo 
5558db1d6eSArnaldo Carvalho de Melo 	return value;
5658db1d6eSArnaldo Carvalho de Melo }
5758db1d6eSArnaldo Carvalho de Melo 
convert_unit(unsigned long value,char * unit)58*6859bc0eSChangbin Du unsigned long convert_unit(unsigned long value, char *unit)
59*6859bc0eSChangbin Du {
60*6859bc0eSChangbin Du 	double v = convert_unit_double((double)value, unit);
61*6859bc0eSChangbin Du 
62*6859bc0eSChangbin Du 	return (unsigned long)v;
63*6859bc0eSChangbin Du }
64*6859bc0eSChangbin Du 
unit_number__scnprintf(char * buf,size_t size,u64 n)6558db1d6eSArnaldo Carvalho de Melo int unit_number__scnprintf(char *buf, size_t size, u64 n)
6658db1d6eSArnaldo Carvalho de Melo {
6758db1d6eSArnaldo Carvalho de Melo 	char unit[4] = "BKMG";
6858db1d6eSArnaldo Carvalho de Melo 	int i = 0;
6958db1d6eSArnaldo Carvalho de Melo 
7058db1d6eSArnaldo Carvalho de Melo 	while (((n / 1024) > 1) && (i < 3)) {
7158db1d6eSArnaldo Carvalho de Melo 		n /= 1024;
7258db1d6eSArnaldo Carvalho de Melo 		i++;
7358db1d6eSArnaldo Carvalho de Melo 	}
7458db1d6eSArnaldo Carvalho de Melo 
7558db1d6eSArnaldo Carvalho de Melo 	return scnprintf(buf, size, "%" PRIu64 "%c", n, unit[i]);
7658db1d6eSArnaldo Carvalho de Melo }
77