1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * Helper functions to skip white spaces, find tokens, find separators and free
31 * memory.
32 */
33
34#include <errno.h>
35#include <stdlib.h>
36#include <string.h>
37#include <ctype.h>
38
39#include "commp_util.h"
40
41
42/*
43 * Skip to the next non-whitespace
44 */
45int
46commp_skip_white_space(const char **begin, const char *end)
47{
48	while (*begin < end) {
49		if (!isspace(**begin))
50			return (0);
51		(*begin)++;
52	}
53	return (1);
54}
55
56/*
57 * Finds the token in the char buffer. *current will be pointing to the
58 * token when function returns. If the char buffer has leading token,
59 * it returns 1.
60 */
61int
62commp_find_token(const char **begin, const char **current,  const char *end,
63    char token, boolean_t last)
64{
65	*current = *begin;
66	while (*current < end) {
67		if (!last && (**current == token))
68			break;
69		else if (isspace(**current))
70			return (1);
71		(*current)++;
72	}
73	/* Checks for leading white space */
74	if (*current == *begin)
75		return (1);
76	else
77		return (0);
78}
79
80/*
81 * atoi function
82 */
83int
84commp_atoi(const char *begin, const char *end, int *num)
85{
86	boolean_t	num_found = B_FALSE;
87
88	*num = 0;
89	while (begin < end) {
90		if (isdigit(*begin)) {
91			*num = (*num * 10) + (*begin - '0');
92			num_found = B_TRUE;
93			begin++;
94		} else {
95			break;
96		}
97	}
98	if (!num_found || (begin != end))
99		return (EINVAL);
100	return (0);
101}
102
103/*
104 * Given a string converts it to unsigned long long int.
105 */
106int
107commp_strtoull(const char *begin, const char *end, uint64_t *num)
108{
109	boolean_t	num_found = B_FALSE;
110
111	*num = 0;
112	while (begin < end) {
113		if (isdigit(*begin)) {
114			*num = (*num * 10) + (*begin - '0');
115			num_found = B_TRUE;
116			begin++;
117		} else {
118			break;
119		}
120	}
121	if (!num_found || (begin != end))
122		return (EINVAL);
123	return (0);
124}
125
126/*
127 * Given a string converts it to unsigned byte
128 */
129int
130commp_strtoub(const char *begin, const char *end, uint8_t *num)
131{
132	boolean_t	num_found = B_FALSE;
133
134	*num = 0;
135	while (begin < end) {
136		if (isdigit(*begin)) {
137			*num = (*num * 10) + (*begin - '0');
138			num_found = B_TRUE;
139			begin++;
140		} else {
141			break;
142		}
143	}
144	if (!num_found || (begin != end))
145		return (EINVAL);
146	return (0);
147}
148
149/*
150 * Given a string converts it to unsigned int
151 */
152int
153commp_atoui(const char *begin, const char *end, uint_t *num)
154{
155	boolean_t	num_found = B_FALSE;
156
157	*num = 0;
158	while (begin < end) {
159		if (isdigit(*begin)) {
160			*num = (*num * 10) + (*begin - '0');
161			num_found = B_TRUE;
162			begin++;
163		} else {
164			break;
165		}
166	}
167	if (!num_found || (begin != end))
168		return (EINVAL);
169	return (0);
170}
171
172/*
173 * allocates memory and copies string to new memory
174 */
175int
176commp_add_str(char **dest, const char *src, int len)
177{
178	if (len == 0)
179		return (EINVAL);
180	(*dest) = calloc(1, len + 1);
181	if (*dest == NULL)
182		return (ENOMEM);
183	(void) strncpy(*dest, src, len);
184	return (0);
185}
186
187/*
188 * This function converts strings like "5d" to equivalent time in secs.
189 * For eg. 1h = 3600, 10d = 86400
190 */
191int
192commp_time_to_secs(const char *begin, const char *end, uint64_t *num)
193{
194	uint_t		factor = 0;
195
196	if (!isdigit(*(end - 1))) {
197		switch (*(end - 1)) {
198			case 'd':
199				factor = COMMP_SECS_IN_DAY;
200				break;
201			case 'h':
202				factor = COMMP_SECS_IN_HOUR;
203				break;
204			case 'm':
205				factor = COMMP_SECS_IN_MIN;
206				break;
207			case 's':
208				factor = 1;
209				break;
210			default:
211				return (EINVAL);
212		}
213		--end;
214	}
215	if (commp_strtoull(begin, end, num) != 0)
216		return (EINVAL);
217	if (factor != 0)
218		(*num) = (*num) * factor;
219	return (0);
220}
221