8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libinstzones / common / zones_str.c
blobbc79f0665c67234706e824ecc1b1d3a145b3194a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * Module: zones_str.c
30 * Group: libinstzones
31 * Description: Private functions used by zones library functions to manipulate
32 * strings
34 * Public Methods:
36 * _z_strAddToken - Add a token to a string
37 * _z_strContainsToken - Does a given string contain a specified substring
38 * _z_strGetToken - Get a separator delimited token from a string
39 * _z_strGetToken_r - Get separator delimited token from string to fixed buffer
40 * _z_strPrintf - Create string from printf style format and arguments
41 * _z_strPrintf_r - Create string from printf style format and arguments
42 * _z_strRemoveLeadingWhitespace - Remove leading whitespace from string
43 * _z_strRemoveToken - Remove a token from a string
47 * System includes
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <ctype.h>
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <string.h>
57 #include <strings.h>
58 #include <stdarg.h>
59 #include <limits.h>
60 #include <stropts.h>
61 #include <libintl.h>
62 #include <locale.h>
63 #include <assert.h>
66 * local includes
69 #include "instzones_lib.h"
70 #include "zones_strings.h"
73 * Private structures
77 * Library Function Prototypes
81 * Local Function Prototypes
85 * Global internal (private) declarations
89 * *****************************************************************************
90 * global external (public) functions
91 * *****************************************************************************
95 * Name: _z_strAddToken
96 * Synopsis: Add a token to a string
97 * Description: Append a token (sequence of one or more characters) to a
98 * string that is in allocated space - create new string if
99 * no string to append to exists
100 * Arguments: a_old - [RO, *RW] - (char **)
101 * - Pointer to handle to string to append token to
102 * == NULL - new string is created
103 * a_new - [RO, *RO] - (char *)
104 * - Pointer to string representing token to append
105 * to the end of the "a_old" string
106 * == NULL - no action is performed
107 * a_new[0] == '\0' - no action is performed
108 * a_separator - [RO, *RO] - (char)
109 * - One character placed between the old (existing)
110 * string and the new token to be added IF the old
111 * string exists and is not empty (zero length)
112 * Returns: void
113 * CAUTION: The old (existing) string must be allocated space (via lu_mem*
114 * or _z_str* methods) - it must not be a static or inline
115 * character string
116 * NOTE: The old (existing) string may be freed with 'free'
117 * if a token is appended to it
118 * NOTE: Any string returned in 'a_old' is placed in new storage for the
119 * calling method. The caller must use 'free' to dispose
120 * of the storage once the token string is no longer needed.
123 void
124 _z_strAddToken(char **a_old, char *a_new, char a_separator)
126 /* entry assertions */
128 assert(a_old != NULL);
129 assert(a_separator != '\0');
131 /* if token to add is null or token is zero length, just return */
133 if (a_new == NULL || *a_new == '\0') {
134 return;
137 /* make sure that new token does not contain the separator */
139 assert(strchr(a_new, (int)a_separator) == NULL);
141 /* if old string is empty (zero length), deallocate */
143 if ((*a_old != NULL) && ((*a_old)[0] == '\0')) {
144 /* *a_old is set to NULL by free */
145 free(*a_old);
146 *a_old = NULL;
149 /* if old string exists, append separator and token */
151 if (*a_old != NULL) {
152 char *p;
153 p = _z_strPrintf("%s%c%s", *a_old, a_separator, a_new);
154 free(*a_old);
155 *a_old = p;
156 return;
159 /* old string does not exist - return duplicate of token */
161 assert(*a_old == NULL);
162 *a_old = _z_strdup(a_new);
166 * Name: _z_strContainsToken
167 * Synopsis: Does a given string contain a specified substring
168 * Description: Determine if a given substring exists in a larger string
169 * Arguments: a_string - [RO, *RO] - (char *)
170 * Pointer to string to look for substring in
171 * a_token - [RO, *RO] - (char *)
172 * Pointer to substring to look for in larger string
173 * Results: boolean_t
174 * B_TRUE - substring exists in larger string
175 * B_FALSE - substring does NOT exist in larger string
176 * NOTE: The substring must match on a "token" basis; that is, the
177 * substring must exist in the larger string delineated with
178 * either spaces or tabs to match.
181 boolean_t
182 _z_strContainsToken(char *a_string, char *a_token, char *a_separators)
184 char *lasts;
185 char *current;
186 char *p;
188 /* entry assertions */
190 assert(a_separators != NULL);
191 assert(*a_separators != '\0');
194 * if token is not supplied, no string provided,
195 * or the string is an empty string, return false
198 if (a_token == NULL || a_string == NULL || *a_string == '\0') {
199 return (B_FALSE);
202 /* if no string provided, return false */
204 /* if string empty (zero length), return false */
206 /* duplicate larger string because strtok_r changes it */
208 p = _z_strdup(a_string);
210 lasts = p;
212 /* scan each token looking for a match */
214 while ((current = strtok_r(NULL, a_separators, &lasts)) !=
215 NULL) {
216 if (strcmp(current, a_token) == 0) {
217 free(p);
218 return (B_TRUE);
222 /* free up temporary storage */
224 free(p);
226 /* not found */
228 return (B_FALSE);
232 * Name: _z_strGetToken
233 * Synopsis: Get a separator delimited token from a string
234 * Description: Given a string and a list of one or more separators,
235 * return the position specified token (sequence of one or
236 * more characters that do not include any of the separators)
237 * Arguments: r_sep - [*RW] - (char *)
238 * - separator that ended the token returned
239 * - NOTE: this is a pointer to a "char", e.g.:
240 * - char a;
241 * - _z_strGetToken(&a, ...)
242 * a_string - [RO, *RO] - (char *)
243 * - pointer to string to extract token from
244 * a_index - [RO, *RO] - (int)
245 * - Index of token to return; '0' is first matching
246 * token, '1' is second matching token, etc.
247 * a_separators - [RO, *RO] - (char *)
248 * - String containing one or more characters that
249 * can separate one "token" from another
250 * Returns: char *
251 * == NULL - no token matching criteria found
252 * != NULL - token matching criteria
253 * NOTE: Any token string returned is placed in new storage for the
254 * calling method. The caller must use 'free' to dispose
255 * of the storage once the token string is no longer needed.
258 char *
259 _z_strGetToken(char *r_sep, char *a_string, int a_index, char *a_separators)
261 char *p;
262 char *q;
263 char *lasts;
265 /* entry assertions */
267 assert(a_string != NULL);
268 assert(a_index >= 0);
269 assert(a_separators != NULL);
270 assert(*a_separators != '\0');
272 /* if returned separator requested, reset to null until token found */
274 if (r_sep != NULL) {
275 *r_sep = '\0';
278 /* duplicate original string before breaking down into tokens */
280 p = _z_strdup(a_string);
282 lasts = p;
284 /* scan for separators and return 'index'th token found */
286 while (q = strtok_r(NULL, a_separators, &lasts)) {
287 /* retrieve separator if requested */
289 if (r_sep != NULL) {
290 char *x;
292 x = strpbrk(a_string, a_separators);
293 if (x != NULL) {
294 *r_sep = *x;
298 /* if this is the 'index'th token requested return it */
300 if (a_index-- == 0) {
301 char *tmp;
303 /* duplicate token into its own storage */
305 tmp = _z_strdup(q);
307 /* free up copy of original input string */
309 free(p);
311 /* return token found */
313 return (tmp);
318 * token not found
321 /* free up copy of original input string */
323 free(p);
325 /* return NULL pointer (token not found) */
327 return (NULL);
331 * Name: _z_strGetToken_r
332 * Synopsis: Get separator delimited token from a string into a fixed buffer
333 * Description: Given a string and a list of one or more separators,
334 * return the position specified token (sequence of one or
335 * more characters that do not include any of the separators)
336 * into a specified buffer of a fixed maximum size
337 * Arguments: r_sep - [*RW] - (char *)
338 * - separator that ended the token returned
339 * - NOTE: this is a pointer to a "char", e.g.:
340 * - char a;
341 * - _z_strGetToken(&a, ...)
342 * a_string - [RO, *RO] - (char *)
343 * - pointer to string to extract token from
344 * a_index - [RO, *RO] - (int)
345 * - Index of token to return; '0' is first matching
346 * token, '1' is second matching token, etc.
347 * a_separators - [RO, *RO] - (char *)
348 * - String containing one or more characters that
349 * can separate one "token" from another
350 * a_buf - [RO, *RW] - (char *)
351 * - Pointer to buffer used as storage space for the
352 * returned token - the returned token is always
353 * null terminated
354 * a_buf[0] == '\0' - no token meeting criteria found
355 * a_buf[0] != '\0' - token meeting criteria returned
356 * a_bufLen - [RO, *RO] - (int)
357 * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
358 * bytes will be placed in 'a_buf' - the returned
359 * token is always null terminated
360 * Returns: void
363 void
364 _z_strGetToken_r(char *r_sep, char *a_string, int a_index,
365 char *a_separators, char *a_buf, int a_bufLen)
367 char *p;
368 char *q;
369 char *lasts;
371 /* entry assertions */
373 assert(a_string != NULL);
374 assert(a_index >= 0);
375 assert(a_separators != NULL);
376 assert(*a_separators != '\0');
377 assert(a_buf != NULL);
378 assert(a_bufLen > 0);
380 /* reset returned separator */
382 if (r_sep != NULL) {
383 *r_sep = '\0';
386 /* zero out contents of return buffer */
388 bzero(a_buf, a_bufLen);
390 /* duplicate original string before breaking down into tokens */
392 p = _z_strdup(a_string);
394 lasts = p;
396 /* scan for separators and return 'index'th token found */
398 while (q = strtok_r(NULL, a_separators, &lasts)) {
399 /* retrieve separator if requested */
401 if (r_sep != NULL) {
402 char *x;
403 x = strpbrk(a_string, a_separators);
404 if (x != NULL) {
405 *r_sep = *x;
409 /* if this is the 'index'th token requested return it */
411 if (a_index-- == 0) {
412 /* copy as many characters as possible to return buf */
414 (void) strncpy(a_buf, q, a_bufLen-1);
415 break;
419 /* free up copy of original input string */
421 free(p);
425 * Name: _z_strPrintf
426 * Synopsis: Create string from printf style format and arguments
427 * Description: Call to convert a printf style format and arguments into a
428 * string of characters placed in allocated storage
429 * Arguments: format - [RO, RO*] (char *)
430 * printf-style format for string to be formatted
431 * VARG_LIST - [RO] (?)
432 * arguments as appropriate to 'format' specified
433 * Returns: char *
434 * A string representing the printf conversion results
435 * NOTE: Any string returned is placed in new storage for the
436 * calling method. The caller must use 'free' to dispose
437 * of the storage once the string is no longer needed.
438 * Errors: If the string cannot be created, the process exits
441 /*PRINTFLIKE1*/
442 char *
443 _z_strPrintf(char *a_format, ...)
445 va_list ap;
446 size_t vres = 0;
447 char bfr[1];
448 char *rstr = NULL;
450 /* entry assertions */
452 assert(a_format != NULL);
453 assert(*a_format != '\0');
455 /* determine size of the message in bytes */
457 va_start(ap, a_format);
458 vres = vsnprintf(bfr, 1, a_format, ap);
459 va_end(ap);
461 assert(vres > 0);
462 assert(vres < LINE_MAX);
464 /* allocate storage to hold the message */
466 rstr = (char *)_z_calloc(vres+2);
468 /* generate the results of the printf conversion */
470 va_start(ap, a_format);
471 vres = vsnprintf(rstr, vres+1, a_format, ap);
472 va_end(ap);
474 assert(vres > 0);
475 assert(vres < LINE_MAX);
476 assert(*rstr != '\0');
478 /* return the results */
480 return (rstr);
484 * Name: _z_strPrintf_r
485 * Synopsis: Create string from printf style format and arguments
486 * Description: Call to convert a printf style format and arguments into a
487 * string of characters placed in allocated storage
488 * Arguments: a_buf - [RO, *RW] - (char *)
489 * - Pointer to buffer used as storage space for the
490 * returned string created
491 * a_bufLen - [RO, *RO] - (int)
492 * - Size of 'a_buf' in bytes - a maximum of 'a_bufLen-1'
493 * bytes will be placed in 'a_buf' - the returned
494 * string is always null terminated
495 * a_format - [RO, RO*] (char *)
496 * printf-style format for string to be formatted
497 * VARG_LIST - [RO] (?)
498 * arguments as appropriate to 'format' specified
499 * Returns: void
502 /*PRINTFLIKE3*/
503 void
504 _z_strPrintf_r(char *a_buf, int a_bufLen, char *a_format, ...)
506 va_list ap;
507 size_t vres = 0;
509 /* entry assertions */
511 assert(a_format != NULL);
512 assert(*a_format != '\0');
513 assert(a_buf != NULL);
514 assert(a_bufLen > 1);
516 /* generate the results of the printf conversion */
518 va_start(ap, a_format);
519 vres = vsnprintf(a_buf, a_bufLen-1, a_format, ap);
520 va_end(ap);
522 assert(vres > 0);
523 assert(vres < a_bufLen);
525 a_buf[a_bufLen-1] = '\0';
529 * Name: _z_strRemoveLeadingWhitespace
530 * Synopsis: Remove leading whitespace from string
531 * Description: Remove all leading whitespace characters from a string
532 * Arguments: a_str - [RO, *RW] - (char **)
533 * Pointer to handle to string (in allocated storage) to
534 * remove all leading whitespace from
535 * Returns: void
536 * The input string is modified as follows:
537 * == NULL:
538 * - input string was NULL
539 * - input string is all whitespace
540 * != NULL:
541 * - copy of input string with leading
542 * whitespace removed
543 * CAUTION: The input string must be allocated space (via mem* or
544 * _z_str* methods) - it must not be a static or inline
545 * character string
546 * NOTE: The input string a_str will be freed with 'free'
547 * if it is all whitespace, or if it contains any leading
548 * whitespace characters
549 * NOTE: Any string returned is placed in new storage for the
550 * calling method. The caller must use 'free' to dispose
551 * of the storage once the string is no longer needed.
552 * Errors: If the string cannot be created, the process exits
555 void
556 _z_strRemoveLeadingWhitespace(char **a_str)
558 char *o_str;
560 /* entry assertions */
562 assert(a_str != NULL);
564 /* if string is null, just return */
566 if (*a_str == NULL) {
567 return;
569 o_str = *a_str;
571 /* if string is empty, deallocate and return NULL */
573 if (*o_str == '\0') {
574 /* free string - handle is not reset to NULL by free */
575 free(*a_str);
576 *a_str = NULL;
577 return;
580 /* if first character is not a space, just return */
582 if (!isspace(*o_str)) {
583 return;
586 /* advance past all space characters */
588 while ((*o_str != '\0') && (isspace(*o_str))) {
589 o_str++;
592 /* if string was all space characters, deallocate and return NULL */
594 if (*o_str == '\0') {
595 /* free string - *a_str is not reset to NULL by free */
596 free(*a_str);
597 *a_str = NULL;
598 return;
601 /* have non-space/null byte, return dup, deallocate original */
603 free(*a_str);
604 *a_str = _z_strdup(o_str);
608 * Name: _z_strRemoveToken
609 * Synopsis: Remove a token from a string
610 * Description: Remove a token (sequence of one or more characters) from a
611 * string that is in allocated space
612 * Arguments: r_string - [RO, *RW] - (char **)
613 * - Pointer to handle to string to remove token from
614 * a_token - [RO, *RO] - (char *)
615 * Pointer to token (substring) to look for and remove
616 * from r_string provided
617 * a_separators - [RO, *RO] - (char *)
618 * - String containing one or more characters that
619 * separate one "token" from another in r_string
620 * a_index - [RO, *RO] - (int)
621 * - Index of token to remove; '0' is first matching
622 * token, '1' is second matching token, etc.
623 * Returns: void
624 * CAUTION: The input string must be allocated space (via lu_mem* or
625 * _z_str* methods) - it must not be a static or inline
626 * character string
627 * NOTE: The input string r_string will be freed with 'free'
628 * if the token to be removed is found
629 * NOTE: Any token string returned is placed in new storage for the
630 * calling method. The caller must use 'free' to dispose
631 * of the storage once the token string is no longer needed.
632 * Errors: If the new token string cannot be created, the process exits
635 void
636 _z_strRemoveToken(char **r_string, char *a_token, char *a_separators,
637 int a_index)
639 char *a_string;
640 char *copyString;
641 char sep = 0;
642 int copyLength;
643 int i;
645 /* entry assertions */
647 assert(r_string != NULL);
648 assert(a_token != NULL);
649 assert(*a_token != '\0');
650 assert(a_separators != NULL);
651 assert(*a_separators != '\0');
653 /* simple case: input string is null; return empty string */
655 a_string = *r_string;
656 if (*a_string == '\0') {
657 return;
660 /* simple case: token == input string; return empty string */
662 if (strcmp(a_string, a_token) == 0) {
664 * deallocate input string; free doesn't
665 * set *r_string to NULL
667 free(*r_string);
668 *r_string = NULL;
669 return;
672 /* simple case: token not in input string: return */
674 if (!_z_strContainsToken(a_string, a_token, a_separators)) {
675 return;
679 * Pick apart the old string building the new one as we go along
680 * removing the first occurance of the token provided
683 copyLength = (strlen(a_string)-strlen(a_token))+2;
684 copyString = (char *)_z_calloc(copyLength);
686 for (i = 0; ; i++) {
687 char *p;
689 p = _z_strGetToken(&sep, a_string, i, a_separators);
690 if (p == NULL) {
691 break;
694 if ((strcmp(p, a_token) == 0) && (a_index-- == 0)) {
695 free(p);
696 continue;
699 if (*copyString) {
700 assert(sep != '\0');
701 (void) strncat(copyString, &sep, 1);
704 (void) strcat(copyString, p);
705 free(p);
708 free(*r_string);
709 assert(*copyString);
710 *r_string = copyString;