1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_BASE_STRINGUTILS_H__ 12 #define WEBRTC_BASE_STRINGUTILS_H__ 13 14 #include <ctype.h> 15 #include <stdarg.h> 16 #include <stdio.h> 17 #include <string.h> 18 19 #if defined(WEBRTC_WIN) 20 #include <malloc.h> 21 #include <wchar.h> 22 #define alloca _alloca 23 #endif // WEBRTC_WIN 24 25 #if defined(WEBRTC_POSIX) 26 #ifdef BSD 27 #include <stdlib.h> 28 #else // BSD 29 #include <alloca.h> 30 #endif // !BSD 31 #endif // WEBRTC_POSIX 32 33 #include <string> 34 35 #include "webrtc/base/basictypes.h" 36 37 /////////////////////////////////////////////////////////////////////////////// 38 // Generic string/memory utilities 39 /////////////////////////////////////////////////////////////////////////////// 40 41 #define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE))) 42 43 namespace rtc { 44 45 // Complement to memset. Verifies memory consists of count bytes of value c. 46 bool memory_check(const void* memory, int c, size_t count); 47 48 // Determines whether the simple wildcard pattern matches target. 49 // Alpha characters in pattern match case-insensitively. 50 // Asterisks in pattern match 0 or more characters. 51 // Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true 52 bool string_match(const char* target, const char* pattern); 53 54 } // namespace rtc 55 56 /////////////////////////////////////////////////////////////////////////////// 57 // Rename a bunch of common string functions so they are consistent across 58 // platforms and between char and wchar_t variants. 59 // Here is the full list of functions that are unified: 60 // strlen, strcmp, stricmp, strncmp, strnicmp 61 // strchr, vsnprintf, strtoul, tolowercase 62 // tolowercase is like tolower, but not compatible with end-of-file value 63 // 64 // It's not clear if we will ever use wchar_t strings on unix. In theory, 65 // all strings should be Utf8 all the time, except when interfacing with Win32 66 // APIs that require Utf16. 67 /////////////////////////////////////////////////////////////////////////////// 68 69 inline char tolowercase(char c) { 70 return static_cast<char>(tolower(c)); 71 } 72 73 #if defined(WEBRTC_WIN) 74 75 inline size_t strlen(const wchar_t* s) { 76 return wcslen(s); 77 } 78 inline int strcmp(const wchar_t* s1, const wchar_t* s2) { 79 return wcscmp(s1, s2); 80 } 81 inline int stricmp(const wchar_t* s1, const wchar_t* s2) { 82 return _wcsicmp(s1, s2); 83 } 84 inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 85 return wcsncmp(s1, s2, n); 86 } 87 inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 88 return _wcsnicmp(s1, s2, n); 89 } 90 inline const wchar_t* strchr(const wchar_t* s, wchar_t c) { 91 return wcschr(s, c); 92 } 93 inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) { 94 return wcsstr(haystack, needle); 95 } 96 #ifndef vsnprintf 97 inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) { 98 return _vsnwprintf(buf, n, fmt, args); 99 } 100 #endif // !vsnprintf 101 inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) { 102 return wcstoul(snum, end, base); 103 } 104 inline wchar_t tolowercase(wchar_t c) { 105 return static_cast<wchar_t>(towlower(c)); 106 } 107 108 #endif // WEBRTC_WIN 109 110 #if defined(WEBRTC_POSIX) 111 112 inline int _stricmp(const char* s1, const char* s2) { 113 return strcasecmp(s1, s2); 114 } 115 inline int _strnicmp(const char* s1, const char* s2, size_t n) { 116 return strncasecmp(s1, s2, n); 117 } 118 119 #endif // WEBRTC_POSIX 120 121 /////////////////////////////////////////////////////////////////////////////// 122 // Traits simplifies porting string functions to be CTYPE-agnostic 123 /////////////////////////////////////////////////////////////////////////////// 124 125 namespace rtc { 126 127 const size_t SIZE_UNKNOWN = static_cast<size_t>(-1); 128 129 template<class CTYPE> 130 struct Traits { 131 // STL string type 132 //typedef XXX string; 133 // Null-terminated string 134 //inline static const CTYPE* empty_str(); 135 }; 136 137 /////////////////////////////////////////////////////////////////////////////// 138 // String utilities which work with char or wchar_t 139 /////////////////////////////////////////////////////////////////////////////// 140 141 template<class CTYPE> 142 inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) { 143 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str()); 144 } 145 146 template<class CTYPE> 147 const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) { 148 for (size_t i=0; str[i]; ++i) { 149 for (size_t j=0; chs[j]; ++j) { 150 if (str[i] == chs[j]) { 151 return str + i; 152 } 153 } 154 } 155 return 0; 156 } 157 158 template<class CTYPE> 159 const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) { 160 for (size_t i=0; i<slen && str[i]; ++i) { 161 if (str[i] == ch) { 162 return str + i; 163 } 164 } 165 return 0; 166 } 167 168 template<class CTYPE> 169 size_t strlenn(const CTYPE* buffer, size_t buflen) { 170 size_t bufpos = 0; 171 while (buffer[bufpos] && (bufpos < buflen)) { 172 ++bufpos; 173 } 174 return bufpos; 175 } 176 177 // Safe versions of strncpy, strncat, snprintf and vsnprintf that always 178 // null-terminate. 179 180 template<class CTYPE> 181 size_t strcpyn(CTYPE* buffer, size_t buflen, 182 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 183 if (buflen <= 0) 184 return 0; 185 186 if (srclen == SIZE_UNKNOWN) { 187 srclen = strlenn(source, buflen - 1); 188 } else if (srclen >= buflen) { 189 srclen = buflen - 1; 190 } 191 memcpy(buffer, source, srclen * sizeof(CTYPE)); 192 buffer[srclen] = 0; 193 return srclen; 194 } 195 196 template<class CTYPE> 197 size_t strcatn(CTYPE* buffer, size_t buflen, 198 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 199 if (buflen <= 0) 200 return 0; 201 202 size_t bufpos = strlenn(buffer, buflen - 1); 203 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen); 204 } 205 206 // Some compilers (clang specifically) require vsprintfn be defined before 207 // sprintfn. 208 template<class CTYPE> 209 size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, 210 va_list args) { 211 int len = vsnprintf(buffer, buflen, format, args); 212 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) { 213 len = static_cast<int>(buflen - 1); 214 buffer[len] = 0; 215 } 216 return len; 217 } 218 219 template<class CTYPE> 220 size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...); 221 template<class CTYPE> 222 size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) { 223 va_list args; 224 va_start(args, format); 225 size_t len = vsprintfn(buffer, buflen, format, args); 226 va_end(args); 227 return len; 228 } 229 230 /////////////////////////////////////////////////////////////////////////////// 231 // Allow safe comparing and copying ascii (not UTF-8) with both wide and 232 // non-wide character strings. 233 /////////////////////////////////////////////////////////////////////////////// 234 235 inline int asccmp(const char* s1, const char* s2) { 236 return strcmp(s1, s2); 237 } 238 inline int ascicmp(const char* s1, const char* s2) { 239 return _stricmp(s1, s2); 240 } 241 inline int ascncmp(const char* s1, const char* s2, size_t n) { 242 return strncmp(s1, s2, n); 243 } 244 inline int ascnicmp(const char* s1, const char* s2, size_t n) { 245 return _strnicmp(s1, s2, n); 246 } 247 inline size_t asccpyn(char* buffer, size_t buflen, 248 const char* source, size_t srclen = SIZE_UNKNOWN) { 249 return strcpyn(buffer, buflen, source, srclen); 250 } 251 252 #if defined(WEBRTC_WIN) 253 254 typedef wchar_t(*CharacterTransformation)(wchar_t); 255 inline wchar_t identity(wchar_t c) { return c; } 256 int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n, 257 CharacterTransformation transformation); 258 259 inline int asccmp(const wchar_t* s1, const char* s2) { 260 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity); 261 } 262 inline int ascicmp(const wchar_t* s1, const char* s2) { 263 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase); 264 } 265 inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) { 266 return ascii_string_compare(s1, s2, n, identity); 267 } 268 inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) { 269 return ascii_string_compare(s1, s2, n, tolowercase); 270 } 271 size_t asccpyn(wchar_t* buffer, size_t buflen, 272 const char* source, size_t srclen = SIZE_UNKNOWN); 273 274 #endif // WEBRTC_WIN 275 276 /////////////////////////////////////////////////////////////////////////////// 277 // Traits<char> specializations 278 /////////////////////////////////////////////////////////////////////////////// 279 280 template<> 281 struct Traits<char> { 282 typedef std::string string; 283 inline static const char* empty_str() { return ""; } 284 }; 285 286 /////////////////////////////////////////////////////////////////////////////// 287 // Traits<wchar_t> specializations (Windows only, currently) 288 /////////////////////////////////////////////////////////////////////////////// 289 290 #if defined(WEBRTC_WIN) 291 292 template<> 293 struct Traits<wchar_t> { 294 typedef std::wstring string; 295 inline static const wchar_t* empty_str() { return L""; } 296 }; 297 298 #endif // WEBRTC_WIN 299 300 // Replaces all occurrences of "search" with "replace". 301 void replace_substrs(const char *search, 302 size_t search_len, 303 const char *replace, 304 size_t replace_len, 305 std::string *s); 306 307 // True iff s1 starts with s2. 308 bool starts_with(const char *s1, const char *s2); 309 310 // True iff s1 ends with s2. 311 bool ends_with(const char *s1, const char *s2); 312 313 // Remove leading and trailing whitespaces. 314 std::string string_trim(const std::string& s); 315 316 } // namespace rtc 317 318 #endif // WEBRTC_BASE_STRINGUTILS_H__ 319