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 60namespace talk_base { 61 62// Complement to memset. Verifies memory consists of count bytes of value c. 63bool 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 69bool 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 86inline char tolowercase(char c) { 87 return static_cast<char>(tolower(c)); 88} 89 90#ifdef WIN32 91 92inline size_t strlen(const wchar_t* s) { 93 return wcslen(s); 94} 95inline int strcmp(const wchar_t* s1, const wchar_t* s2) { 96 return wcscmp(s1, s2); 97} 98inline int stricmp(const wchar_t* s1, const wchar_t* s2) { 99 return _wcsicmp(s1, s2); 100} 101inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 102 return wcsncmp(s1, s2, n); 103} 104inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) { 105 return _wcsnicmp(s1, s2, n); 106} 107inline const wchar_t* strchr(const wchar_t* s, wchar_t c) { 108 return wcschr(s, c); 109} 110inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) { 111 return wcsstr(haystack, needle); 112} 113#ifndef vsnprintf 114inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) { 115 return _vsnwprintf(buf, n, fmt, args); 116} 117#endif // !vsnprintf 118inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) { 119 return wcstoul(snum, end, base); 120} 121inline wchar_t tolowercase(wchar_t c) { 122 return static_cast<wchar_t>(towlower(c)); 123} 124 125#endif // WIN32 126 127#ifdef POSIX 128 129inline int _stricmp(const char* s1, const char* s2) { 130 return strcasecmp(s1, s2); 131} 132inline int _strnicmp(const char* s1, const char* s2, size_t n) { 133 return strncasecmp(s1, s2, n); 134} 135 136#endif // POSIX 137 138/////////////////////////////////////////////////////////////////////////////// 139// Traits simplifies porting string functions to be CTYPE-agnostic 140/////////////////////////////////////////////////////////////////////////////// 141 142namespace talk_base { 143 144const size_t SIZE_UNKNOWN = static_cast<size_t>(-1); 145 146template<class CTYPE> 147struct Traits { 148 // STL string type 149 //typedef XXX string; 150 // Null-terminated string 151 //inline static const CTYPE* empty_str(); 152}; 153 154/////////////////////////////////////////////////////////////////////////////// 155// String utilities which work with char or wchar_t 156/////////////////////////////////////////////////////////////////////////////// 157 158template<class CTYPE> 159inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = NULL) { 160 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str()); 161} 162 163template<class CTYPE> 164const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) { 165 for (size_t i=0; str[i]; ++i) { 166 for (size_t j=0; chs[j]; ++j) { 167 if (str[i] == chs[j]) { 168 return str + i; 169 } 170 } 171 } 172 return 0; 173} 174 175template<class CTYPE> 176const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) { 177 for (size_t i=0; i<slen && str[i]; ++i) { 178 if (str[i] == ch) { 179 return str + i; 180 } 181 } 182 return 0; 183} 184 185template<class CTYPE> 186size_t strlenn(const CTYPE* buffer, size_t buflen) { 187 size_t bufpos = 0; 188 while (buffer[bufpos] && (bufpos < buflen)) { 189 ++bufpos; 190 } 191 return bufpos; 192} 193 194// Safe versions of strncpy, strncat, snprintf and vsnprintf that always 195// null-terminate. 196 197template<class CTYPE> 198size_t strcpyn(CTYPE* buffer, size_t buflen, 199 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 200 if (buflen <= 0) 201 return 0; 202 203 if (srclen == SIZE_UNKNOWN) { 204 srclen = strlenn(source, buflen - 1); 205 } else if (srclen >= buflen) { 206 srclen = buflen - 1; 207 } 208 memcpy(buffer, source, srclen * sizeof(CTYPE)); 209 buffer[srclen] = 0; 210 return srclen; 211} 212 213template<class CTYPE> 214size_t strcatn(CTYPE* buffer, size_t buflen, 215 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) { 216 if (buflen <= 0) 217 return 0; 218 219 size_t bufpos = strlenn(buffer, buflen - 1); 220 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen); 221} 222 223// Some compilers (clang specifically) require vsprintfn be defined before 224// sprintfn. 225template<class CTYPE> 226size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, 227 va_list args) { 228 int len = vsnprintf(buffer, buflen, format, args); 229 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) { 230 len = static_cast<int>(buflen - 1); 231 buffer[len] = 0; 232 } 233 return len; 234} 235 236template<class CTYPE> 237size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...); 238template<class CTYPE> 239size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) { 240 va_list args; 241 va_start(args, format); 242 size_t len = vsprintfn(buffer, buflen, format, args); 243 va_end(args); 244 return len; 245} 246 247/////////////////////////////////////////////////////////////////////////////// 248// Allow safe comparing and copying ascii (not UTF-8) with both wide and 249// non-wide character strings. 250/////////////////////////////////////////////////////////////////////////////// 251 252inline int asccmp(const char* s1, const char* s2) { 253 return strcmp(s1, s2); 254} 255inline int ascicmp(const char* s1, const char* s2) { 256 return _stricmp(s1, s2); 257} 258inline int ascncmp(const char* s1, const char* s2, size_t n) { 259 return strncmp(s1, s2, n); 260} 261inline int ascnicmp(const char* s1, const char* s2, size_t n) { 262 return _strnicmp(s1, s2, n); 263} 264inline size_t asccpyn(char* buffer, size_t buflen, 265 const char* source, size_t srclen = SIZE_UNKNOWN) { 266 return strcpyn(buffer, buflen, source, srclen); 267} 268 269#ifdef WIN32 270 271typedef wchar_t(*CharacterTransformation)(wchar_t); 272inline wchar_t identity(wchar_t c) { return c; } 273int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n, 274 CharacterTransformation transformation); 275 276inline int asccmp(const wchar_t* s1, const char* s2) { 277 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity); 278} 279inline int ascicmp(const wchar_t* s1, const char* s2) { 280 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase); 281} 282inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) { 283 return ascii_string_compare(s1, s2, n, identity); 284} 285inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) { 286 return ascii_string_compare(s1, s2, n, tolowercase); 287} 288size_t asccpyn(wchar_t* buffer, size_t buflen, 289 const char* source, size_t srclen = SIZE_UNKNOWN); 290 291#endif // WIN32 292 293/////////////////////////////////////////////////////////////////////////////// 294// Traits<char> specializations 295/////////////////////////////////////////////////////////////////////////////// 296 297template<> 298struct Traits<char> { 299 typedef std::string string; 300 inline static const char* empty_str() { return ""; } 301}; 302 303/////////////////////////////////////////////////////////////////////////////// 304// Traits<wchar_t> specializations (Windows only, currently) 305/////////////////////////////////////////////////////////////////////////////// 306 307#ifdef WIN32 308 309template<> 310struct Traits<wchar_t> { 311 typedef std::wstring string; 312 inline static const wchar_t* Traits<wchar_t>::empty_str() { return L""; } 313}; 314 315#endif // WIN32 316 317// Replaces all occurrences of "search" with "replace". 318void replace_substrs(const char *search, 319 size_t search_len, 320 const char *replace, 321 size_t replace_len, 322 std::string *s); 323 324// True iff s1 starts with s2. 325bool starts_with(const char *s1, const char *s2); 326 327// True iff s1 ends with s2. 328bool ends_with(const char *s1, const char *s2); 329 330// Remove leading and trailing whitespaces. 331std::string string_trim(const std::string& s); 332 333} // namespace talk_base 334 335#endif // TALK_BASE_STRINGUTILS_H__ 336