1 /**************************************************************************
2  *
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 /**
29  * @file
30  * Platform independent functions for string manipulation.
31  *
32  * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
33  */
34 
35 #ifndef U_STRING_H_
36 #define U_STRING_H_
37 
38 #if !defined(WIN32) && !defined(XF86_LIBC_H)
39 #include <stdio.h>
40 #endif
41 #include <stddef.h>
42 #include <stdarg.h>
43 
44 #include "pipe/p_compiler.h"
45 
46 
47 #ifdef __cplusplus
48 extern "C" {
49 #endif
50 
51 #ifdef _GNU_SOURCE
52 
53 #define util_strchrnul strchrnul
54 
55 #else
56 
57 static INLINE char *
58 util_strchrnul(const char *s, char c)
59 {
60    for (; *s && *s != c; ++s);
61 
62    return (char *)s;
63 }
64 
65 #endif
66 
67 #ifdef WIN32
68 
69 int util_vsnprintf(char *, size_t, const char *, va_list);
70 int util_snprintf(char *str, size_t size, const char *format, ...);
71 
72 static INLINE void
util_vsprintf(char * str,const char * format,va_list ap)73 util_vsprintf(char *str, const char *format, va_list ap)
74 {
75    util_vsnprintf(str, (size_t)-1, format, ap);
76 }
77 
78 static INLINE void
util_sprintf(char * str,const char * format,...)79 util_sprintf(char *str, const char *format, ...)
80 {
81    va_list ap;
82    va_start(ap, format);
83    util_vsnprintf(str, (size_t)-1, format, ap);
84    va_end(ap);
85 }
86 
87 static INLINE char *
util_strchr(const char * s,char c)88 util_strchr(const char *s, char c)
89 {
90    char *p = util_strchrnul(s, c);
91 
92    return *p ? p : NULL;
93 }
94 
95 static INLINE char*
util_strncat(char * dst,const char * src,size_t n)96 util_strncat(char *dst, const char *src, size_t n)
97 {
98    char *p = dst + strlen(dst);
99    const char *q = src;
100    size_t i;
101 
102    for (i = 0; i < n && *q != '\0'; ++i)
103        *p++ = *q++;
104    *p = '\0';
105 
106    return dst;
107 }
108 
109 static INLINE int
util_strcmp(const char * s1,const char * s2)110 util_strcmp(const char *s1, const char *s2)
111 {
112    unsigned char u1, u2;
113 
114    while (1) {
115       u1 = (unsigned char) *s1++;
116       u2 = (unsigned char) *s2++;
117       if (u1 != u2)
118 	 return u1 - u2;
119       if (u1 == '\0')
120 	 return 0;
121    }
122    return 0;
123 }
124 
125 static INLINE int
util_strncmp(const char * s1,const char * s2,size_t n)126 util_strncmp(const char *s1, const char *s2, size_t n)
127 {
128    unsigned char u1, u2;
129 
130    while (n-- > 0) {
131       u1 = (unsigned char) *s1++;
132       u2 = (unsigned char) *s2++;
133       if (u1 != u2)
134 	 return u1 - u2;
135       if (u1 == '\0')
136 	 return 0;
137    }
138    return 0;
139 }
140 
141 static INLINE char *
util_strstr(const char * haystack,const char * needle)142 util_strstr(const char *haystack, const char *needle)
143 {
144    const char *p = haystack;
145    size_t len = strlen(needle);
146 
147    for (; (p = util_strchr(p, *needle)) != 0; p++) {
148       if (util_strncmp(p, needle, len) == 0) {
149 	 return (char *)p;
150       }
151    }
152    return NULL;
153 }
154 
155 static INLINE void *
util_memmove(void * dest,const void * src,size_t n)156 util_memmove(void *dest, const void *src, size_t n)
157 {
158    char *p = (char *)dest;
159    const char *q = (const char *)src;
160    if (dest < src) {
161       while (n--)
162 	 *p++ = *q++;
163    }
164    else
165    {
166       p += n;
167       q += n;
168       while (n--)
169 	 *--p = *--q;
170    }
171    return dest;
172 }
173 
174 
175 #else
176 
177 #define util_vsnprintf vsnprintf
178 #define util_snprintf snprintf
179 #define util_vsprintf vsprintf
180 #define util_sprintf sprintf
181 #define util_strchr strchr
182 #define util_strcmp strcmp
183 #define util_strncmp strncmp
184 #define util_strncat strncat
185 #define util_strstr strstr
186 #define util_memmove memmove
187 
188 #endif
189 
190 
191 /**
192  * Printable string buffer
193  */
194 struct util_strbuf
195 {
196    char *str;
197    char *ptr;
198    size_t left;
199 };
200 
201 
202 static INLINE void
util_strbuf_init(struct util_strbuf * sbuf,char * str,size_t size)203 util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size)
204 {
205    sbuf->str = str;
206    sbuf->str[0] = 0;
207    sbuf->ptr = sbuf->str;
208    sbuf->left = size;
209 }
210 
211 
212 static INLINE void
util_strbuf_printf(struct util_strbuf * sbuf,const char * format,...)213 util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...)
214 {
215    if(sbuf->left > 1) {
216       size_t written;
217       va_list ap;
218       va_start(ap, format);
219       written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap);
220       va_end(ap);
221       sbuf->ptr += written;
222       sbuf->left -= written;
223    }
224 }
225 
226 
227 
228 #ifdef __cplusplus
229 }
230 #endif
231 
232 #endif /* U_STRING_H_ */
233