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
43namespace rtc {
44
45// Complement to memset.  Verifies memory consists of count bytes of value c.
46bool 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
52bool 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
69inline char tolowercase(char c) {
70  return static_cast<char>(tolower(c));
71}
72
73#if defined(WEBRTC_WIN)
74
75inline size_t strlen(const wchar_t* s) {
76  return wcslen(s);
77}
78inline int strcmp(const wchar_t* s1, const wchar_t* s2) {
79  return wcscmp(s1, s2);
80}
81inline int stricmp(const wchar_t* s1, const wchar_t* s2) {
82  return _wcsicmp(s1, s2);
83}
84inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
85  return wcsncmp(s1, s2, n);
86}
87inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
88  return _wcsnicmp(s1, s2, n);
89}
90inline const wchar_t* strchr(const wchar_t* s, wchar_t c) {
91  return wcschr(s, c);
92}
93inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
94  return wcsstr(haystack, needle);
95}
96#ifndef vsnprintf
97inline 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
101inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
102  return wcstoul(snum, end, base);
103}
104inline 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
112inline int _stricmp(const char* s1, const char* s2) {
113  return strcasecmp(s1, s2);
114}
115inline 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
125namespace rtc {
126
127const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
128
129template<class CTYPE>
130struct 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
141template<class CTYPE>
142inline 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
146template<class CTYPE>
147const 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
158template<class CTYPE>
159const 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
168template<class CTYPE>
169size_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
180template<class CTYPE>
181size_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
196template<class CTYPE>
197size_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.
208template<class CTYPE>
209size_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
219template<class CTYPE>
220size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
221template<class CTYPE>
222size_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
235inline int asccmp(const char* s1, const char* s2) {
236  return strcmp(s1, s2);
237}
238inline int ascicmp(const char* s1, const char* s2) {
239  return _stricmp(s1, s2);
240}
241inline int ascncmp(const char* s1, const char* s2, size_t n) {
242  return strncmp(s1, s2, n);
243}
244inline int ascnicmp(const char* s1, const char* s2, size_t n) {
245  return _strnicmp(s1, s2, n);
246}
247inline 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
254typedef wchar_t(*CharacterTransformation)(wchar_t);
255inline wchar_t identity(wchar_t c) { return c; }
256int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
257                         CharacterTransformation transformation);
258
259inline int asccmp(const wchar_t* s1, const char* s2) {
260  return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
261}
262inline int ascicmp(const wchar_t* s1, const char* s2) {
263  return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
264}
265inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
266  return ascii_string_compare(s1, s2, n, identity);
267}
268inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
269  return ascii_string_compare(s1, s2, n, tolowercase);
270}
271size_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
280template<>
281struct 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
292template<>
293struct Traits<wchar_t> {
294  typedef std::wstring string;
295  inline static const wchar_t* Traits<wchar_t>::empty_str() { return L""; }
296};
297
298#endif  // WEBRTC_WIN
299
300// Replaces all occurrences of "search" with "replace".
301void 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.
308bool starts_with(const char *s1, const char *s2);
309
310// True iff s1 ends with s2.
311bool ends_with(const char *s1, const char *s2);
312
313// Remove leading and trailing whitespaces.
314std::string string_trim(const std::string& s);
315
316}  // namespace rtc
317
318#endif // WEBRTC_BASE_STRINGUTILS_H__
319