Home | History | Annotate | Download | only in base
      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