1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_BASE_STRINGUTILS_H__ 29 #define TALK_BASE_STRINGUTILS_H__ 30 31 #include <ctype.h> 32 #include <stdarg.h> 33 #include <stdio.h> 34 35 #ifdef WIN32 36 #include <malloc.h> 37 #include <wchar.h> 38 #define alloca _alloca 39 #endif // WIN32 40 41 #ifdef POSIX 42 #ifdef BSD 43 #include <stdlib.h> 44 #else // BSD 45 #include <alloca.h> 46 #endif // !BSD 47 #endif // POSIX 48 49 #include <cstring> 50 #include <string> 51 52 #include "talk/base/basictypes.h" 53 54 /////////////////////////////////////////////////////////////////////////////// 55 // Generic string/memory utilities 56 /////////////////////////////////////////////////////////////////////////////// 57 58 #define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE))) 59 60 namespace talk_base { 61 62 // Complement to memset. Verifies memory consists of count bytes of value c. 63 bool memory_check(const void* memory, int c, size_t count); 64 65 // Determines whether the simple wildcard pattern matches target. 66 // Alpha characters in pattern match case-insensitively. 67 // Asterisks in pattern match 0 or more characters. 68 // Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true 69 bool string_match(const char* target, const char* pattern); 70 71 } // namespace talk_base 72 73 /////////////////////////////////////////////////////////////////////////////// 74 // Rename a bunch of common string functions so they are consistent across 75 // platforms and between char and wchar_t variants. 76 // Here is the full list of functions that are unified: 77 // strlen, strcmp, stricmp, strncmp, strnicmp 78 // strchr, vsnprintf, strtoul, tolowercase 79 // tolowercase is like tolower, but not compatible with end-of-file value 80 // 81 // It's not clear if we will ever use wchar_t strings on unix. In theory, 82 // all strings should be Utf8 all the time, except when interfacing with Win32 83 // APIs that require Utf16. 84 /////////////////////////////////////////////////////////////////////////////// 85 86 inline char tolowercase(char c) { 87 return static_cast<char>(tolower(c)); 88 } 89 90 #ifdef WIN32 91 92 inline size_t strlen(const wchar_t* s) { 93 return wcslen(s); 94 } 95 inline int strcmp(const wchar_t* s1, const wchar_t* s2) { 96 return wcscmp(s1, s2); 97 } 98 inline int stricmp(const wchar_t* s1, const wchar_t* s2) { 99 return _wcsicmp(s1, s2); 100 } 101 inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 102 return wcsncmp(s1, s2, n); 103 } 104 inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 105 return _wcsnicmp(s1, s2, n); 106 } 107 inline const wchar_t* strchr(const wchar_t* s, wchar_t c) { 108 return wcschr(s, c); 109 } 110 inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) { 111 return wcsstr(haystack, needle); 112 } 113 #ifndef vsnprintf 114 inline int vsnprintf(char* buf, size_t n, const char* fmt, va_list args) { 115 return _vsnprintf(buf, n, fmt, args); 116 } 117 inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) { 118 return _vsnwprintf(buf, n, fmt, args); 119 } 120 #endif // !vsnprintf 121 inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) { 122 return wcstoul(snum, end, base); 123 } 124 inline wchar_t tolowercase(wchar_t c) { 125 return static_cast<wchar_t>(towlower(c)); 126 } 127 128 #endif // WIN32 129 130 #ifdef POSIX 131 132 inline int _stricmp(const char* s1, const char* s2) { 133 return strcasecmp(s1, s2); 134 } 135 inline int _strnicmp(const char* s1, const char* s2, size_t n) { 136 return strncasecmp(s1, s2, n); 137 } 138 139 #endif // POSIX 140 141 /////////////////////////////////////////////////////////////////////////////// 142 // Traits simplifies porting string functions to be CTYPE-agnostic 143 /////////////////////////////////////////////////////////////////////////////// 144 145 namespace talk_base { 146 147 const size_t SIZE_UNKNOWN = static_cast<size_t>(-1); 148 149 template<class CTYPE> 150 struct Traits { 151 // STL string type 152 //typedef XXX string; 153 // Null-terminated string 154 //inline static const CTYPE* empty_str(); 155 }; 156 157 /////////////////////////////////////////////////////////////////////////////// 158 // String utilities which work with char or wchar_t 159 /////////////////////////////////////////////////////////////////////////////// 160 161 template<class CTYPE> 162 inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) { 163 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str()); 164 } 165 166 template<class CTYPE> 167 const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) { 168 for (size_t i=0; str[i]; ++i) { 169 for (size_t j=0; chs[j]; ++j) { 170 if (str[i] == chs[j]) { 171 return str + i; 172 } 173 } 174 } 175 return 0; 176 } 177 178 template<class CTYPE> 179 const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) { 180 for (size_t i=0; i<slen && str[i]; ++i) { 181 if (str[i] == ch) { 182 return str + i; 183 } 184 } 185 return 0; 186 } 187 188 template<class CTYPE> 189 size_t strlenn(const CTYPE* buffer, size_t buflen) { 190 size_t bufpos = 0; 191 while (buffer[bufpos] && (bufpos < buflen)) { 192 ++bufpos; 193 } 194 return bufpos; 195 } 196 197 // Safe versions of strncpy, strncat, snprintf and vsnprintf that always 198 // null-terminate. 199 200 template<class CTYPE> 201 size_t strcpyn(CTYPE* buffer, size_t buflen, 202 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 203 if (buflen <= 0) 204 return 0; 205 206 if (srclen == SIZE_UNKNOWN) { 207 srclen = strlenn(source, buflen - 1); 208 } else if (srclen >= buflen) { 209 srclen = buflen - 1; 210 } 211 memcpy(buffer, source, srclen * sizeof(CTYPE)); 212 buffer[srclen] = 0; 213 return srclen; 214 } 215 216 template<class CTYPE> 217 size_t strcatn(CTYPE* buffer, size_t buflen, 218 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 219 if (buflen <= 0) 220 return 0; 221 222 size_t bufpos = strlenn(buffer, buflen - 1); 223 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen); 224 } 225 226 // Some compilers (clang specifically) require vsprintfn be defined before 227 // sprintfn. 228 template<class CTYPE> 229 size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, 230 va_list args) { 231 int len = vsnprintf(buffer, buflen, format, args); 232 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) { 233 len = static_cast<int>(buflen - 1); 234 buffer[len] = 0; 235 } 236 return len; 237 } 238 239 template<class CTYPE> 240 size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...); 241 /* This works to get GCC to notice printf argument mismatches, but then complains of missing implementation of sprintfn<char> 242 template<> 243 size_t sprintfn(char* buffer, size_t buflen, const char* format, ...) 244 GCC_ATTR(format(printf,3,4)); 245 */ 246 template<class CTYPE> 247 size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) { 248 va_list args; 249 va_start(args, format); 250 size_t len = vsprintfn(buffer, buflen, format, args); 251 va_end(args); 252 return len; 253 } 254 255 /////////////////////////////////////////////////////////////////////////////// 256 // Allow safe comparing and copying ascii (not UTF-8) with both wide and 257 // non-wide character strings. 258 /////////////////////////////////////////////////////////////////////////////// 259 260 inline int asccmp(const char* s1, const char* s2) { 261 return strcmp(s1, s2); 262 } 263 inline int ascicmp(const char* s1, const char* s2) { 264 return _stricmp(s1, s2); 265 } 266 inline int ascncmp(const char* s1, const char* s2, size_t n) { 267 return strncmp(s1, s2, n); 268 } 269 inline int ascnicmp(const char* s1, const char* s2, size_t n) { 270 return _strnicmp(s1, s2, n); 271 } 272 inline size_t asccpyn(char* buffer, size_t buflen, 273 const char* source, size_t srclen = SIZE_UNKNOWN) { 274 return strcpyn(buffer, buflen, source, srclen); 275 } 276 277 #ifdef WIN32 278 279 typedef wchar_t(*CharacterTransformation)(wchar_t); 280 inline wchar_t identity(wchar_t c) { return c; } 281 int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n, 282 CharacterTransformation transformation); 283 284 inline int asccmp(const wchar_t* s1, const char* s2) { 285 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity); 286 } 287 inline int ascicmp(const wchar_t* s1, const char* s2) { 288 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase); 289 } 290 inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) { 291 return ascii_string_compare(s1, s2, n, identity); 292 } 293 inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) { 294 return ascii_string_compare(s1, s2, n, tolowercase); 295 } 296 size_t asccpyn(wchar_t* buffer, size_t buflen, 297 const char* source, size_t srclen = SIZE_UNKNOWN); 298 299 #endif // WIN32 300 301 /////////////////////////////////////////////////////////////////////////////// 302 // Traits<char> specializations 303 /////////////////////////////////////////////////////////////////////////////// 304 305 template<> 306 struct Traits<char> { 307 typedef std::string string; 308 inline static const char* empty_str() { return ""; } 309 }; 310 311 /////////////////////////////////////////////////////////////////////////////// 312 // Traits<wchar_t> specializations (Windows only, currently) 313 /////////////////////////////////////////////////////////////////////////////// 314 315 #ifdef WIN32 316 317 template<> 318 struct Traits<wchar_t> { 319 typedef std::wstring string; 320 inline static const wchar_t* Traits<wchar_t>::empty_str() { return L""; } 321 }; 322 323 #endif // WIN32 324 325 // Replaces all occurrences of "search" with "replace". 326 void replace_substrs(const char *search, 327 size_t search_len, 328 const char *replace, 329 size_t replace_len, 330 std::string *s); 331 332 // True iff s1 starts with s2. 333 bool starts_with(const char *s1, const char *s2); 334 335 // Remove leading and trailing whitespaces. 336 std::string string_trim(const std::string& s); 337 338 } // namespace talk_base 339 340 #endif // TALK_BASE_STRINGUTILS_H__ 341