1 /* Copyright (c) 2008 The NetBSD Foundation, Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25 26 #include "atf-c/detail/text.h" 27 28 #include <errno.h> 29 #include <limits.h> 30 #include <string.h> 31 #include <stdlib.h> 32 33 #include "atf-c/detail/dynstr.h" 34 #include "atf-c/detail/sanity.h" 35 #include "atf-c/error.h" 36 37 atf_error_t 38 atf_text_for_each_word(const char *instr, const char *sep, 39 atf_error_t (*func)(const char *, void *), 40 void *data) 41 { 42 atf_error_t err; 43 char *str, *str2, *last; 44 45 str = strdup(instr); 46 if (str == NULL) { 47 err = atf_no_memory_error(); 48 goto out; 49 } 50 51 err = atf_no_error(); 52 str2 = strtok_r(str, sep, &last); 53 while (str2 != NULL && !atf_is_error(err)) { 54 err = func(str2, data); 55 str2 = strtok_r(NULL, sep, &last); 56 } 57 58 free(str); 59 out: 60 return err; 61 } 62 63 atf_error_t 64 atf_text_format(char **dest, const char *fmt, ...) 65 { 66 atf_error_t err; 67 va_list ap; 68 69 va_start(ap, fmt); 70 err = atf_text_format_ap(dest, fmt, ap); 71 va_end(ap); 72 73 return err; 74 } 75 76 atf_error_t 77 atf_text_format_ap(char **dest, const char *fmt, va_list ap) 78 { 79 atf_error_t err; 80 atf_dynstr_t tmp; 81 va_list ap2; 82 83 va_copy(ap2, ap); 84 err = atf_dynstr_init_ap(&tmp, fmt, ap2); 85 va_end(ap2); 86 if (!atf_is_error(err)) 87 *dest = atf_dynstr_fini_disown(&tmp); 88 89 return err; 90 } 91 92 atf_error_t 93 atf_text_split(const char *str, const char *delim, atf_list_t *words) 94 { 95 atf_error_t err; 96 const char *end; 97 const char *iter; 98 99 err = atf_list_init(words); 100 if (atf_is_error(err)) 101 goto err; 102 103 end = str + strlen(str); 104 INV(*end == '\0'); 105 iter = str; 106 while (iter < end) { 107 const char *ptr; 108 109 INV(iter != NULL); 110 ptr = strstr(iter, delim); 111 if (ptr == NULL) 112 ptr = end; 113 114 INV(ptr >= iter); 115 if (ptr > iter) { 116 atf_dynstr_t word; 117 118 err = atf_dynstr_init_raw(&word, iter, ptr - iter); 119 if (atf_is_error(err)) 120 goto err_list; 121 122 err = atf_list_append(words, atf_dynstr_fini_disown(&word), true); 123 if (atf_is_error(err)) 124 goto err_list; 125 } 126 127 iter = ptr + strlen(delim); 128 } 129 130 INV(!atf_is_error(err)); 131 return err; 132 133 err_list: 134 atf_list_fini(words); 135 err: 136 return err; 137 } 138 139 atf_error_t 140 atf_text_to_bool(const char *str, bool *b) 141 { 142 atf_error_t err; 143 144 if (strcasecmp(str, "yes") == 0 || 145 strcasecmp(str, "true") == 0) { 146 *b = true; 147 err = atf_no_error(); 148 } else if (strcasecmp(str, "no") == 0 || 149 strcasecmp(str, "false") == 0) { 150 *b = false; 151 err = atf_no_error(); 152 } else { 153 /* XXX Not really a libc error. */ 154 err = atf_libc_error(EINVAL, "Cannot convert string '%s' " 155 "to boolean", str); 156 } 157 158 return err; 159 } 160 161 atf_error_t 162 atf_text_to_long(const char *str, long *l) 163 { 164 atf_error_t err; 165 char *endptr; 166 long tmp; 167 168 errno = 0; 169 tmp = strtol(str, &endptr, 10); 170 if (str[0] == '\0' || *endptr != '\0') 171 err = atf_libc_error(EINVAL, "'%s' is not a number", str); 172 else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN)) 173 err = atf_libc_error(ERANGE, "'%s' is out of range", str); 174 else { 175 *l = tmp; 176 err = atf_no_error(); 177 } 178 179 return err; 180 } 181