text.c revision 240116
1193326Sed/*
2193326Sed * Automated Testing Framework (atf)
3193326Sed *
4193326Sed * Copyright (c) 2008 The NetBSD Foundation, Inc.
5193326Sed * All rights reserved.
6193326Sed *
7193326Sed * Redistribution and use in source and binary forms, with or without
8193326Sed * modification, are permitted provided that the following conditions
9193326Sed * are met:
10193326Sed * 1. Redistributions of source code must retain the above copyright
11193326Sed *    notice, this list of conditions and the following disclaimer.
12193326Sed * 2. Redistributions in binary form must reproduce the above copyright
13193326Sed *    notice, this list of conditions and the following disclaimer in the
14193326Sed *    documentation and/or other materials provided with the distribution.
15193326Sed *
16193326Sed * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17193326Sed * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18252723Sdim * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19226890Sdim * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20252723Sdim * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21201361Srdivacky * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22193326Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23245431Sdim * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24218893Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25193326Sed * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26193326Sed * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27193326Sed * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28226890Sdim */
29193326Sed
30193326Sed#include <errno.h>
31193326Sed#include <limits.h>
32193326Sed#include <string.h>
33218893Sdim#include <stdlib.h>
34218893Sdim
35198092Srdivacky#include "atf-c/error.h"
36193326Sed
37193326Sed#include "dynstr.h"
38193326Sed#include "sanity.h"
39193326Sed#include "text.h"
40193326Sed
41198092Srdivackyatf_error_t
42193326Sedatf_text_for_each_word(const char *instr, const char *sep,
43193326Sed                       atf_error_t (*func)(const char *, void *),
44193326Sed                       void *data)
45193326Sed{
46198092Srdivacky    atf_error_t err;
47193326Sed    char *str, *str2, *last;
48198092Srdivacky
49235633Sdim    str = strdup(instr);
50198092Srdivacky    if (str == NULL) {
51193326Sed        err = atf_no_memory_error();
52245431Sdim        goto out;
53245431Sdim    }
54245431Sdim
55193326Sed    err = atf_no_error();
56193326Sed    str2 = strtok_r(str, sep, &last);
57193326Sed    while (str2 != NULL && !atf_is_error(err)) {
58193326Sed        err = func(str2, data);
59193326Sed        str2 = strtok_r(NULL, sep, &last);
60193326Sed    }
61198092Srdivacky
62198092Srdivacky    free(str);
63198092Srdivackyout:
64193326Sed    return err;
65193326Sed}
66193326Sed
67193326Sedatf_error_t
68193326Sedatf_text_format(char **dest, const char *fmt, ...)
69235633Sdim{
70235633Sdim    atf_error_t err;
71235633Sdim    va_list ap;
72193326Sed
73235633Sdim    va_start(ap, fmt);
74235633Sdim    err = atf_text_format_ap(dest, fmt, ap);
75235633Sdim    va_end(ap);
76235633Sdim
77235633Sdim    return err;
78235633Sdim}
79235633Sdim
80235633Sdimatf_error_t
81198092Srdivackyatf_text_format_ap(char **dest, const char *fmt, va_list ap)
82263509Sdim{
83263509Sdim    atf_error_t err;
84193326Sed    atf_dynstr_t tmp;
85198092Srdivacky    va_list ap2;
86193326Sed
87193326Sed    va_copy(ap2, ap);
88193326Sed    err = atf_dynstr_init_ap(&tmp, fmt, ap2);
89193326Sed    va_end(ap2);
90193326Sed    if (!atf_is_error(err))
91198092Srdivacky        *dest = atf_dynstr_fini_disown(&tmp);
92193326Sed
93193326Sed    return err;
94193326Sed}
95193326Sed
96193326Sedatf_error_t
97201361Srdivackyatf_text_split(const char *str, const char *delim, atf_list_t *words)
98193326Sed{
99198092Srdivacky    atf_error_t err;
100198092Srdivacky    const char *end;
101193326Sed    const char *iter;
102198092Srdivacky
103263509Sdim    err = atf_list_init(words);
104263509Sdim    if (atf_is_error(err))
105263509Sdim        goto err;
106263509Sdim
107263509Sdim    end = str + strlen(str);
108263509Sdim    INV(*end == '\0');
109263509Sdim    iter = str;
110263509Sdim    while (iter < end) {
111193326Sed        const char *ptr;
112193326Sed
113193326Sed        INV(iter != NULL);
114263509Sdim        ptr = strstr(iter, delim);
115193326Sed        if (ptr == NULL)
116193326Sed            ptr = end;
117193326Sed
118198092Srdivacky        INV(ptr >= iter);
119193326Sed        if (ptr > iter) {
120193326Sed            atf_dynstr_t word;
121193326Sed
122263509Sdim            err = atf_dynstr_init_raw(&word, iter, ptr - iter);
123263509Sdim            if (atf_is_error(err))
124193326Sed                goto err_list;
125193326Sed
126193326Sed            err = atf_list_append(words, atf_dynstr_fini_disown(&word), true);
127198092Srdivacky            if (atf_is_error(err))
128193326Sed                goto err_list;
129193326Sed        }
130193326Sed
131263509Sdim        iter = ptr + strlen(delim);
132193326Sed    }
133193326Sed
134193326Sed    INV(!atf_is_error(err));
135198092Srdivacky    return err;
136193326Sed
137193326Sederr_list:
138193326Sed    atf_list_fini(words);
139263509Sdimerr:
140263509Sdim    return err;
141193326Sed}
142193326Sed
143193326Sedatf_error_t
144198092Srdivackyatf_text_to_bool(const char *str, bool *b)
145193326Sed{
146193326Sed    atf_error_t err;
147193326Sed
148193326Sed    if (strcasecmp(str, "yes") == 0 ||
149193326Sed        strcasecmp(str, "true") == 0) {
150193326Sed        *b = true;
151226890Sdim        err = atf_no_error();
152193326Sed    } else if (strcasecmp(str, "no") == 0 ||
153193326Sed               strcasecmp(str, "false") == 0) {
154235633Sdim        *b = false;
155235633Sdim        err = atf_no_error();
156193326Sed    } else {
157193326Sed        /* XXX Not really a libc error. */
158226890Sdim        err = atf_libc_error(EINVAL, "Cannot convert string '%s' "
159226890Sdim                             "to boolean", str);
160193326Sed    }
161193326Sed
162226890Sdim    return err;
163226890Sdim}
164226890Sdim
165226890Sdimatf_error_t
166193326Sedatf_text_to_long(const char *str, long *l)
167193326Sed{
168235633Sdim    atf_error_t err;
169235633Sdim    char *endptr;
170235633Sdim    long tmp;
171235633Sdim
172235633Sdim    errno = 0;
173193326Sed    tmp = strtol(str, &endptr, 10);
174193326Sed    if (str[0] == '\0' || *endptr != '\0')
175193326Sed        err = atf_libc_error(EINVAL, "'%s' is not a number", str);
176193326Sed    else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN))
177193326Sed        err = atf_libc_error(ERANGE, "'%s' is out of range", str);
178193326Sed    else {
179218893Sdim        *l = tmp;
180218893Sdim        err = atf_no_error();
181218893Sdim    }
182226890Sdim
183218893Sdim    return err;
184193326Sed}
185193326Sed