blob: b0898c0102863aa0e2fafac99d158167a46e4e9b [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef RTC_BASE_STRINGUTILS_H_
12#define RTC_BASE_STRINGUTILS_H_
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000013
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020014#include <ctype.h>
15#include <stdarg.h>
16#include <stdio.h>
17#include <string.h>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020019#if defined(WEBRTC_WIN)
20#include <malloc.h>
21#include <wchar.h>
Patrik Höglunda8005cf2017-12-13 16:05:42 +010022#include <windows.h>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020023#define alloca _alloca
Henrik Kjellanderc0362762017-06-29 08:03:04 +020024#endif // WEBRTC_WIN
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000025
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020026#if defined(WEBRTC_POSIX)
27#ifdef BSD
28#include <stdlib.h>
29#else // BSD
30#include <alloca.h>
31#endif // !BSD
32#endif // WEBRTC_POSIX
33
34#include <string>
35
36///////////////////////////////////////////////////////////////////////////////
37// Generic string/memory utilities
38///////////////////////////////////////////////////////////////////////////////
39
40#define STACK_ARRAY(TYPE, LEN) static_cast<TYPE*>(::alloca((LEN)*sizeof(TYPE)))
41
42namespace rtc {
43
44// Complement to memset. Verifies memory consists of count bytes of value c.
45bool memory_check(const void* memory, int c, size_t count);
46
47// Determines whether the simple wildcard pattern matches target.
48// Alpha characters in pattern match case-insensitively.
49// Asterisks in pattern match 0 or more characters.
50// Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true
51bool string_match(const char* target, const char* pattern);
52
53} // namespace rtc
54
55///////////////////////////////////////////////////////////////////////////////
56// Rename a bunch of common string functions so they are consistent across
57// platforms and between char and wchar_t variants.
58// Here is the full list of functions that are unified:
59// strlen, strcmp, stricmp, strncmp, strnicmp
60// strchr, vsnprintf, strtoul, tolowercase
61// tolowercase is like tolower, but not compatible with end-of-file value
62//
63// It's not clear if we will ever use wchar_t strings on unix. In theory,
64// all strings should be Utf8 all the time, except when interfacing with Win32
65// APIs that require Utf16.
66///////////////////////////////////////////////////////////////////////////////
67
68inline char tolowercase(char c) {
69 return static_cast<char>(tolower(c));
70}
71
72#if defined(WEBRTC_WIN)
73
74inline size_t strlen(const wchar_t* s) {
75 return wcslen(s);
76}
77inline int strcmp(const wchar_t* s1, const wchar_t* s2) {
78 return wcscmp(s1, s2);
79}
80inline int stricmp(const wchar_t* s1, const wchar_t* s2) {
81 return _wcsicmp(s1, s2);
82}
83inline int strncmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
84 return wcsncmp(s1, s2, n);
85}
86inline int strnicmp(const wchar_t* s1, const wchar_t* s2, size_t n) {
87 return _wcsnicmp(s1, s2, n);
88}
89inline const wchar_t* strchr(const wchar_t* s, wchar_t c) {
90 return wcschr(s, c);
91}
92inline const wchar_t* strstr(const wchar_t* haystack, const wchar_t* needle) {
93 return wcsstr(haystack, needle);
94}
95#ifndef vsnprintf
96inline int vsnprintf(wchar_t* buf, size_t n, const wchar_t* fmt, va_list args) {
97 return _vsnwprintf(buf, n, fmt, args);
98}
99#endif // !vsnprintf
100inline unsigned long strtoul(const wchar_t* snum, wchar_t** end, int base) {
101 return wcstoul(snum, end, base);
102}
103inline wchar_t tolowercase(wchar_t c) {
104 return static_cast<wchar_t>(towlower(c));
105}
106
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200107#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200108
109#if defined(WEBRTC_POSIX)
110
111inline int _stricmp(const char* s1, const char* s2) {
112 return strcasecmp(s1, s2);
113}
114inline int _strnicmp(const char* s1, const char* s2, size_t n) {
115 return strncasecmp(s1, s2, n);
116}
117
118#endif // WEBRTC_POSIX
119
120///////////////////////////////////////////////////////////////////////////////
121// Traits simplifies porting string functions to be CTYPE-agnostic
122///////////////////////////////////////////////////////////////////////////////
123
124namespace rtc {
125
126const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
127
128template<class CTYPE>
129struct Traits {
130 // STL string type
131 //typedef XXX string;
132 // Null-terminated string
133 //inline static const CTYPE* empty_str();
134};
135
136///////////////////////////////////////////////////////////////////////////////
137// String utilities which work with char or wchar_t
138///////////////////////////////////////////////////////////////////////////////
139
140template <class CTYPE>
141inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = nullptr) {
142 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
143}
144
145template<class CTYPE>
146const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
147 for (size_t i=0; str[i]; ++i) {
148 for (size_t j=0; chs[j]; ++j) {
149 if (str[i] == chs[j]) {
150 return str + i;
151 }
152 }
153 }
154 return 0;
155}
156
157template<class CTYPE>
158const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
159 for (size_t i=0; i<slen && str[i]; ++i) {
160 if (str[i] == ch) {
161 return str + i;
162 }
163 }
164 return 0;
165}
166
167template<class CTYPE>
168size_t strlenn(const CTYPE* buffer, size_t buflen) {
169 size_t bufpos = 0;
170 while (buffer[bufpos] && (bufpos < buflen)) {
171 ++bufpos;
172 }
173 return bufpos;
174}
175
176// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
177// null-terminate.
178
179template<class CTYPE>
180size_t strcpyn(CTYPE* buffer, size_t buflen,
181 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
182 if (buflen <= 0)
183 return 0;
184
185 if (srclen == SIZE_UNKNOWN) {
186 srclen = strlenn(source, buflen - 1);
187 } else if (srclen >= buflen) {
188 srclen = buflen - 1;
189 }
190 memcpy(buffer, source, srclen * sizeof(CTYPE));
191 buffer[srclen] = 0;
192 return srclen;
193}
194
195template<class CTYPE>
196size_t strcatn(CTYPE* buffer, size_t buflen,
197 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
198 if (buflen <= 0)
199 return 0;
200
201 size_t bufpos = strlenn(buffer, buflen - 1);
202 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
203}
204
205// Some compilers (clang specifically) require vsprintfn be defined before
206// sprintfn.
207template<class CTYPE>
208size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
209 va_list args) {
210 int len = vsnprintf(buffer, buflen, format, args);
211 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
212 len = static_cast<int>(buflen - 1);
213 buffer[len] = 0;
214 }
215 return len;
216}
217
218template<class CTYPE>
219size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
220template<class CTYPE>
221size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
222 va_list args;
223 va_start(args, format);
224 size_t len = vsprintfn(buffer, buflen, format, args);
225 va_end(args);
226 return len;
227}
228
229///////////////////////////////////////////////////////////////////////////////
230// Allow safe comparing and copying ascii (not UTF-8) with both wide and
231// non-wide character strings.
232///////////////////////////////////////////////////////////////////////////////
233
234inline int asccmp(const char* s1, const char* s2) {
235 return strcmp(s1, s2);
236}
237inline int ascicmp(const char* s1, const char* s2) {
238 return _stricmp(s1, s2);
239}
240inline int ascncmp(const char* s1, const char* s2, size_t n) {
241 return strncmp(s1, s2, n);
242}
243inline int ascnicmp(const char* s1, const char* s2, size_t n) {
244 return _strnicmp(s1, s2, n);
245}
246inline size_t asccpyn(char* buffer, size_t buflen,
247 const char* source, size_t srclen = SIZE_UNKNOWN) {
248 return strcpyn(buffer, buflen, source, srclen);
249}
250
251#if defined(WEBRTC_WIN)
252
253typedef wchar_t(*CharacterTransformation)(wchar_t);
254inline wchar_t identity(wchar_t c) { return c; }
255int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
256 CharacterTransformation transformation);
257
258inline int asccmp(const wchar_t* s1, const char* s2) {
259 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
260}
261inline int ascicmp(const wchar_t* s1, const char* s2) {
262 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
263}
264inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
265 return ascii_string_compare(s1, s2, n, identity);
266}
267inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
268 return ascii_string_compare(s1, s2, n, tolowercase);
269}
270size_t asccpyn(wchar_t* buffer, size_t buflen,
271 const char* source, size_t srclen = SIZE_UNKNOWN);
272
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200273#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200274
275///////////////////////////////////////////////////////////////////////////////
276// Traits<char> specializations
277///////////////////////////////////////////////////////////////////////////////
278
279template<>
280struct Traits<char> {
281 typedef std::string string;
282 inline static const char* empty_str() { return ""; }
283};
284
285///////////////////////////////////////////////////////////////////////////////
286// Traits<wchar_t> specializations (Windows only, currently)
287///////////////////////////////////////////////////////////////////////////////
288
289#if defined(WEBRTC_WIN)
290
291template<>
292struct Traits<wchar_t> {
293 typedef std::wstring string;
294 inline static const wchar_t* empty_str() { return L""; }
295};
296
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200297#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200298
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100299///////////////////////////////////////////////////////////////////////////////
300// UTF helpers (Windows only)
301///////////////////////////////////////////////////////////////////////////////
302
303#if defined(WEBRTC_WIN)
304
305inline std::wstring ToUtf16(const char* utf8, size_t len) {
306 int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len),
307 nullptr, 0);
308 wchar_t* ws = STACK_ARRAY(wchar_t, len16);
309 ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len), ws, len16);
310 return std::wstring(ws, len16);
311}
312
313inline std::wstring ToUtf16(const std::string& str) {
314 return ToUtf16(str.data(), str.length());
315}
316
317inline std::string ToUtf8(const wchar_t* wide, size_t len) {
318 int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len),
319 nullptr, 0, nullptr, nullptr);
320 char* ns = STACK_ARRAY(char, len8);
321 ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len), ns, len8,
322 nullptr, nullptr);
323 return std::string(ns, len8);
324}
325
326inline std::string ToUtf8(const wchar_t* wide) {
327 return ToUtf8(wide, wcslen(wide));
328}
329
330inline std::string ToUtf8(const std::wstring& wstr) {
331 return ToUtf8(wstr.data(), wstr.length());
332}
333
334#endif // WEBRTC_WIN
335
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200336// Replaces all occurrences of "search" with "replace".
337void replace_substrs(const char *search,
338 size_t search_len,
339 const char *replace,
340 size_t replace_len,
341 std::string *s);
342
343// True iff s1 starts with s2.
344bool starts_with(const char *s1, const char *s2);
345
346// True iff s1 ends with s2.
347bool ends_with(const char *s1, const char *s2);
348
349// Remove leading and trailing whitespaces.
350std::string string_trim(const std::string& s);
351
352} // namespace rtc
353
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200354#endif // RTC_BASE_STRINGUTILS_H_