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
48extern "C" {
49#endif
50
51#ifdef _GNU_SOURCE
52
53#define util_strchrnul strchrnul
54
55#else
56
57static INLINE char *
58util_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
69int util_vsnprintf(char *, size_t, const char *, va_list);
70int util_snprintf(char *str, size_t size, const char *format, ...);
71
72static INLINE void
73util_vsprintf(char *str, const char *format, va_list ap)
74{
75   util_vsnprintf(str, (size_t)-1, format, ap);
76}
77
78static INLINE void
79util_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
87static INLINE char *
88util_strchr(const char *s, char c)
89{
90   char *p = util_strchrnul(s, c);
91
92   return *p ? p : NULL;
93}
94
95static INLINE char*
96util_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
109static INLINE int
110util_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
125static INLINE int
126util_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
141static INLINE char *
142util_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
155static INLINE void *
156util_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 */
194struct util_strbuf
195{
196   char *str;
197   char *ptr;
198   size_t left;
199};
200
201
202static INLINE void
203util_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
212static INLINE void
213util_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