u_string.h revision 01e04c3f
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@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 <stdlib.h> 42#include <stddef.h> 43#include <stdarg.h> 44#include <string.h> 45 46#include "util/macros.h" // PRINTFLIKE 47 48 49#ifdef __cplusplus 50extern "C" { 51#endif 52 53#ifdef _GNU_SOURCE 54 55#define util_strchrnul strchrnul 56 57#else 58 59static inline char * 60util_strchrnul(const char *s, char c) 61{ 62 for (; *s && *s != c; ++s); 63 64 return (char *)s; 65} 66 67#endif 68 69#ifdef _WIN32 70 71static inline int 72util_vsnprintf(char *str, size_t size, const char *format, va_list ap) 73{ 74 /* We need to use _vscprintf to calculate the length as vsnprintf returns -1 75 * if the number of characters to write is greater than count. 76 */ 77 va_list ap_copy; 78 int ret; 79 va_copy(ap_copy, ap); 80 ret = _vsnprintf(str, size, format, ap); 81 if (ret < 0) { 82 ret = _vscprintf(format, ap_copy); 83 } 84 va_end(ap_copy); 85 return ret; 86} 87 88static inline int 89 PRINTFLIKE(3, 4) 90util_snprintf(char *str, size_t size, const char *format, ...) 91{ 92 va_list ap; 93 int ret; 94 va_start(ap, format); 95 ret = util_vsnprintf(str, size, format, ap); 96 va_end(ap); 97 return ret; 98} 99 100static inline void 101util_vsprintf(char *str, const char *format, va_list ap) 102{ 103 util_vsnprintf(str, (size_t)-1, format, ap); 104} 105 106static inline void 107 PRINTFLIKE(2, 3) 108util_sprintf(char *str, const char *format, ...) 109{ 110 va_list ap; 111 va_start(ap, format); 112 util_vsnprintf(str, (size_t)-1, format, ap); 113 va_end(ap); 114} 115 116static inline int 117util_vasprintf(char **ret, const char *format, va_list ap) 118{ 119 va_list ap_copy; 120 121 /* Compute length of output string first */ 122 va_copy(ap_copy, ap); 123 int r = util_vsnprintf(NULL, 0, format, ap_copy); 124 va_end(ap_copy); 125 126 if (r < 0) 127 return -1; 128 129 *ret = (char *) malloc(r + 1); 130 if (!*ret) 131 return -1; 132 133 /* Print to buffer */ 134 return util_vsnprintf(*ret, r + 1, format, ap); 135} 136 137static inline char * 138util_strchr(const char *s, char c) 139{ 140 char *p = util_strchrnul(s, c); 141 142 return *p ? p : NULL; 143} 144 145static inline char* 146util_strncat(char *dst, const char *src, size_t n) 147{ 148 char *p = dst + strlen(dst); 149 const char *q = src; 150 size_t i; 151 152 for (i = 0; i < n && *q != '\0'; ++i) 153 *p++ = *q++; 154 *p = '\0'; 155 156 return dst; 157} 158 159static inline int 160util_strcmp(const char *s1, const char *s2) 161{ 162 unsigned char u1, u2; 163 164 while (1) { 165 u1 = (unsigned char) *s1++; 166 u2 = (unsigned char) *s2++; 167 if (u1 != u2) 168 return u1 - u2; 169 if (u1 == '\0') 170 return 0; 171 } 172 return 0; 173} 174 175static inline int 176util_strncmp(const char *s1, const char *s2, size_t n) 177{ 178 unsigned char u1, u2; 179 180 while (n-- > 0) { 181 u1 = (unsigned char) *s1++; 182 u2 = (unsigned char) *s2++; 183 if (u1 != u2) 184 return u1 - u2; 185 if (u1 == '\0') 186 return 0; 187 } 188 return 0; 189} 190 191static inline char * 192util_strstr(const char *haystack, const char *needle) 193{ 194 const char *p = haystack; 195 size_t len = strlen(needle); 196 197 for (; (p = util_strchr(p, *needle)) != 0; p++) { 198 if (util_strncmp(p, needle, len) == 0) { 199 return (char *)p; 200 } 201 } 202 return NULL; 203} 204 205 206#define util_strcasecmp stricmp 207#define util_strdup _strdup 208 209#else 210 211#define util_vsnprintf vsnprintf 212#define util_snprintf snprintf 213#define util_vsprintf vsprintf 214#define util_vasprintf vasprintf 215#define util_sprintf sprintf 216#define util_strchr strchr 217#define util_strcmp strcmp 218#define util_strncmp strncmp 219#define util_strncat strncat 220#define util_strstr strstr 221#define util_strcasecmp strcasecmp 222#define util_strdup strdup 223 224#endif 225 226 227#ifdef __cplusplus 228} 229#endif 230 231#endif /* U_STRING_H_ */ 232