1/*
2 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like.  Any license provided herein, whether implied or
15 * otherwise, applies only to this software file.  Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA  94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 */
32#include <stdio.h>
33#include <sys/param.h>
34
35#include "bytes_by_prefix.h"
36
37/****************************************************************************
38 * bytes_by_prefix(s)
39 *
40 * Computes the number of bytes described by string s.  s is assumed to be
41 * a base 10 positive (ie. >= 0) number followed by an optional single
42 * character multiplier.  The following multipliers are supported:
43 *
44 *              char    mult
45 *              -----------------
46 *              b       BSIZE  or BBSIZE
47 *              k       1024 bytes
48 *              K       1024 * sizeof(long)
49 *              m       2^20 (1048576)
50 *              M       2^20 (1048576 * sizeof(long)
51 *              g       2^30 (1073741824)
52 *              G       2^30 (1073741824) * sizeof(long)
53 *
54 * for instance, "1k" and "1024" would both cause bytes_by_prefix to return 1024
55 *
56 * Returns -1 if mult is an invalid character, or if the integer portion of
57 * s is not a positive integer.
58 *
59 ****************************************************************************/
60
61#ifdef DEV_BSIZE
62#define B_MULT	DEV_BSIZE	/* block size */
63#else
64#warning DEV_BSIZE is not defined, defaulting to 512
65#define B_MULT	512
66#endif
67
68#define K_MULT	1024		/* Kilo or 2^10 */
69#define M_MULT	1048576		/* Mega or 2^20 */
70#define G_MULT	1073741824	/* Giga or 2^30 */
71#define T_MULT	1099511627776	/* tera or 2^40 */
72
73int bytes_by_prefix(char *s)
74{
75	char mult, junk;
76	int nconv;
77	float num;
78	int result;
79
80	nconv = sscanf(s, "%f%c%c", &num, &mult, &junk);
81	if (nconv == 0 || nconv == 3)
82		return -1;
83
84	if (nconv == 1) {
85		result = num;
86		return result < 0 ? -1 : result;
87	}
88
89	switch (mult) {
90	case 'b':
91		result = (int)(num * (float)B_MULT);
92		break;
93	case 'k':
94		result = (int)(num * (float)K_MULT);
95		break;
96	case 'K':
97		result = (int)((num * (float)K_MULT) * sizeof(long));
98		break;
99	case 'm':
100		result = (int)(num * (float)M_MULT);
101		break;
102	case 'M':
103		result = (int)((num * (float)M_MULT) * sizeof(long));
104		break;
105	case 'g':
106		result = (int)(num * (float)G_MULT);
107		break;
108	case 'G':
109		result = (int)((num * (float)G_MULT) * sizeof(long));
110		break;
111	default:
112		return -1;
113	}
114
115	if (result < 0)
116		return -1;
117
118	return result;
119}
120
121long lbytes_by_prefix(char *s)
122{
123	char mult, junk;
124	int nconv;
125	float num;
126	long result;
127
128	nconv = sscanf(s, "%f%c%c", &num, &mult, &junk);
129	if (nconv == 0 || nconv == 3)
130		return -1;
131
132	if (nconv == 1) {
133		result = (long)num;
134		return result < 0 ? -1 : result;
135	}
136
137	switch (mult) {
138	case 'b':
139		result = (long)(num * (float)B_MULT);
140		break;
141	case 'k':
142		result = (long)(num * (float)K_MULT);
143		break;
144	case 'K':
145		result = (long)((num * (float)K_MULT) * sizeof(long));
146		break;
147	case 'm':
148		result = (long)(num * (float)M_MULT);
149		break;
150	case 'M':
151		result = (long)((num * (float)M_MULT) * sizeof(long));
152		break;
153	case 'g':
154		result = (long)(num * (float)G_MULT);
155		break;
156	case 'G':
157		result = (long)((num * (float)G_MULT) * sizeof(long));
158		break;
159	default:
160		return -1;
161	}
162
163	if (result < 0)
164		return -1;
165
166	return result;
167}
168
169/*
170 * Force 64 bits number when compiled as 32 IRIX binary.
171 * This allows for a number bigger than 2G.
172 */
173long long llbytes_by_prefix(char *s)
174{
175	char mult, junk;
176	int nconv;
177	double num;
178	long long result;
179
180	nconv = sscanf(s, "%lf%c%c", &num, &mult, &junk);
181	if (nconv == 0 || nconv == 3)
182		return -1;
183	if (nconv == 1) {
184		result = (long long)num;
185		return result < 0 ? -1 : result;
186	}
187
188	switch (mult) {
189	case 'b':
190		result = (long long)(num * (float)B_MULT);
191		break;
192	case 'k':
193		result = (long long)(num * (float)K_MULT);
194		break;
195	case 'K':
196		result = (long long)((num * (float)K_MULT) * sizeof(long long));
197		break;
198	case 'm':
199		result = (long long)(num * (float)M_MULT);
200		break;
201	case 'M':
202		result = (long long)((num * (float)M_MULT) * sizeof(long long));
203		break;
204	case 'g':
205		result = (long long)(num * (float)G_MULT);
206		break;
207	case 'G':
208		result = (long long)((num * (float)G_MULT) * sizeof(long long));
209		break;
210	default:
211		return -1;
212	}
213
214	if (result < 0)
215		return -1;
216
217	return result;
218}
219