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