1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 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 VMWARE 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 <jfonseca (at) vmware.com> 33 */ 34 35 #ifndef U_STRING_H_ 36 #define U_STRING_H_ 37 38 #if !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 #include "util/macros.h" // PRINTFLIKE 46 47 48 #ifdef __cplusplus 49 extern "C" { 50 #endif 51 52 #ifdef _GNU_SOURCE 53 54 #define util_strchrnul strchrnul 55 56 #else 57 58 static inline char * 59 util_strchrnul(const char *s, char c) 60 { 61 for (; *s && *s != c; ++s); 62 63 return (char *)s; 64 } 65 66 #endif 67 68 #ifdef _WIN32 69 70 static inline int 71 util_vsnprintf(char *str, size_t size, const char *format, va_list ap) 72 { 73 /* We need to use _vscprintf to calculate the length as vsnprintf returns -1 74 * if the number of characters to write is greater than count. 75 */ 76 va_list ap_copy; 77 int ret; 78 va_copy(ap_copy, ap); 79 ret = _vsnprintf(str, size, format, ap); 80 if (ret < 0) { 81 ret = _vscprintf(format, ap_copy); 82 } 83 return ret; 84 } 85 86 static inline int 87 PRINTFLIKE(3, 4) 88 util_snprintf(char *str, size_t size, const char *format, ...) 89 { 90 va_list ap; 91 int ret; 92 va_start(ap, format); 93 ret = util_vsnprintf(str, size, format, ap); 94 va_end(ap); 95 return ret; 96 } 97 98 static inline void 99 util_vsprintf(char *str, const char *format, va_list ap) 100 { 101 util_vsnprintf(str, (size_t)-1, format, ap); 102 } 103 104 static inline void 105 PRINTFLIKE(2, 3) 106 util_sprintf(char *str, const char *format, ...) 107 { 108 va_list ap; 109 va_start(ap, format); 110 util_vsnprintf(str, (size_t)-1, format, ap); 111 va_end(ap); 112 } 113 114 static inline char * 115 util_strchr(const char *s, char c) 116 { 117 char *p = util_strchrnul(s, c); 118 119 return *p ? p : NULL; 120 } 121 122 static inline char* 123 util_strncat(char *dst, const char *src, size_t n) 124 { 125 char *p = dst + strlen(dst); 126 const char *q = src; 127 size_t i; 128 129 for (i = 0; i < n && *q != '\0'; ++i) 130 *p++ = *q++; 131 *p = '\0'; 132 133 return dst; 134 } 135 136 static inline int 137 util_strcmp(const char *s1, const char *s2) 138 { 139 unsigned char u1, u2; 140 141 while (1) { 142 u1 = (unsigned char) *s1++; 143 u2 = (unsigned char) *s2++; 144 if (u1 != u2) 145 return u1 - u2; 146 if (u1 == '\0') 147 return 0; 148 } 149 return 0; 150 } 151 152 static inline int 153 util_strncmp(const char *s1, const char *s2, size_t n) 154 { 155 unsigned char u1, u2; 156 157 while (n-- > 0) { 158 u1 = (unsigned char) *s1++; 159 u2 = (unsigned char) *s2++; 160 if (u1 != u2) 161 return u1 - u2; 162 if (u1 == '\0') 163 return 0; 164 } 165 return 0; 166 } 167 168 static inline char * 169 util_strstr(const char *haystack, const char *needle) 170 { 171 const char *p = haystack; 172 size_t len = strlen(needle); 173 174 for (; (p = util_strchr(p, *needle)) != 0; p++) { 175 if (util_strncmp(p, needle, len) == 0) { 176 return (char *)p; 177 } 178 } 179 return NULL; 180 } 181 182 static inline void * 183 util_memmove(void *dest, const void *src, size_t n) 184 { 185 char *p = (char *)dest; 186 const char *q = (const char *)src; 187 if (dest < src) { 188 while (n--) 189 *p++ = *q++; 190 } 191 else 192 { 193 p += n; 194 q += n; 195 while (n--) 196 *--p = *--q; 197 } 198 return dest; 199 } 200 201 202 #define util_strcasecmp stricmp 203 204 #else 205 206 #define util_vsnprintf vsnprintf 207 #define util_snprintf snprintf 208 #define util_vsprintf vsprintf 209 #define util_sprintf sprintf 210 #define util_strchr strchr 211 #define util_strcmp strcmp 212 #define util_strncmp strncmp 213 #define util_strncat strncat 214 #define util_strstr strstr 215 #define util_memmove memmove 216 #define util_strcasecmp strcasecmp 217 218 #endif 219 220 221 /** 222 * Printable string buffer 223 */ 224 struct util_strbuf 225 { 226 char *str; 227 char *ptr; 228 size_t left; 229 }; 230 231 232 static inline void 233 util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size) 234 { 235 sbuf->str = str; 236 sbuf->str[0] = 0; 237 sbuf->ptr = sbuf->str; 238 sbuf->left = size; 239 } 240 241 242 static inline void 243 util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...) 244 { 245 if(sbuf->left > 1) { 246 size_t written; 247 va_list ap; 248 va_start(ap, format); 249 written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap); 250 va_end(ap); 251 sbuf->ptr += written; 252 sbuf->left -= written; 253 } 254 } 255 256 257 258 #ifdef __cplusplus 259 } 260 #endif 261 262 #endif /* U_STRING_H_ */ 263