]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/atf/atf-c/detail/text.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / atf / atf-c / detail / text.c
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 }