blob: 686402c1f12c467665e240f47a1b9b43de7876c8 [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
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020044// Determines whether the simple wildcard pattern matches target.
45// Alpha characters in pattern match case-insensitively.
46// Asterisks in pattern match 0 or more characters.
47// Ex: string_match("www.TEST.GOOGLE.COM", "www.*.com") -> true
48bool string_match(const char* target, const char* pattern);
49
50} // namespace rtc
51
52///////////////////////////////////////////////////////////////////////////////
Niels Möllere98c3de2017-12-15 14:10:09 +010053// Rename a few common string functions so they are consistent across platforms.
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020054// tolowercase is like tolower, but not compatible with end-of-file value
55//
56// It's not clear if we will ever use wchar_t strings on unix. In theory,
57// all strings should be Utf8 all the time, except when interfacing with Win32
58// APIs that require Utf16.
59///////////////////////////////////////////////////////////////////////////////
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020060inline char tolowercase(char c) {
61 return static_cast<char>(tolower(c));
62}
63
64#if defined(WEBRTC_WIN)
65
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020066inline wchar_t tolowercase(wchar_t c) {
67 return static_cast<wchar_t>(towlower(c));
68}
69
Henrik Kjellanderc0362762017-06-29 08:03:04 +020070#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020071
72#if defined(WEBRTC_POSIX)
73
74inline int _stricmp(const char* s1, const char* s2) {
75 return strcasecmp(s1, s2);
76}
77inline int _strnicmp(const char* s1, const char* s2, size_t n) {
78 return strncasecmp(s1, s2, n);
79}
80
81#endif // WEBRTC_POSIX
82
83///////////////////////////////////////////////////////////////////////////////
84// Traits simplifies porting string functions to be CTYPE-agnostic
85///////////////////////////////////////////////////////////////////////////////
86
87namespace rtc {
88
89const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
90
91template<class CTYPE>
92struct Traits {
93 // STL string type
94 //typedef XXX string;
95 // Null-terminated string
96 //inline static const CTYPE* empty_str();
97};
98
99///////////////////////////////////////////////////////////////////////////////
100// String utilities which work with char or wchar_t
101///////////////////////////////////////////////////////////////////////////////
102
103template <class CTYPE>
104inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = nullptr) {
105 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
106}
107
108template<class CTYPE>
109const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
110 for (size_t i=0; str[i]; ++i) {
111 for (size_t j=0; chs[j]; ++j) {
112 if (str[i] == chs[j]) {
113 return str + i;
114 }
115 }
116 }
117 return 0;
118}
119
120template<class CTYPE>
121const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
122 for (size_t i=0; i<slen && str[i]; ++i) {
123 if (str[i] == ch) {
124 return str + i;
125 }
126 }
127 return 0;
128}
129
130template<class CTYPE>
131size_t strlenn(const CTYPE* buffer, size_t buflen) {
132 size_t bufpos = 0;
133 while (buffer[bufpos] && (bufpos < buflen)) {
134 ++bufpos;
135 }
136 return bufpos;
137}
138
139// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
140// null-terminate.
141
142template<class CTYPE>
143size_t strcpyn(CTYPE* buffer, size_t buflen,
144 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
145 if (buflen <= 0)
146 return 0;
147
148 if (srclen == SIZE_UNKNOWN) {
149 srclen = strlenn(source, buflen - 1);
150 } else if (srclen >= buflen) {
151 srclen = buflen - 1;
152 }
153 memcpy(buffer, source, srclen * sizeof(CTYPE));
154 buffer[srclen] = 0;
155 return srclen;
156}
157
158template<class CTYPE>
159size_t strcatn(CTYPE* buffer, size_t buflen,
160 const CTYPE* source, size_t srclen = SIZE_UNKNOWN) {
161 if (buflen <= 0)
162 return 0;
163
164 size_t bufpos = strlenn(buffer, buflen - 1);
165 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
166}
167
168// Some compilers (clang specifically) require vsprintfn be defined before
169// sprintfn.
170template<class CTYPE>
171size_t vsprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format,
172 va_list args) {
173 int len = vsnprintf(buffer, buflen, format, args);
174 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
175 len = static_cast<int>(buflen - 1);
176 buffer[len] = 0;
177 }
178 return len;
179}
180
181template<class CTYPE>
182size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
183template<class CTYPE>
184size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
185 va_list args;
186 va_start(args, format);
187 size_t len = vsprintfn(buffer, buflen, format, args);
188 va_end(args);
189 return len;
190}
191
192///////////////////////////////////////////////////////////////////////////////
193// Allow safe comparing and copying ascii (not UTF-8) with both wide and
194// non-wide character strings.
195///////////////////////////////////////////////////////////////////////////////
196
197inline int asccmp(const char* s1, const char* s2) {
198 return strcmp(s1, s2);
199}
200inline int ascicmp(const char* s1, const char* s2) {
201 return _stricmp(s1, s2);
202}
203inline int ascncmp(const char* s1, const char* s2, size_t n) {
204 return strncmp(s1, s2, n);
205}
206inline int ascnicmp(const char* s1, const char* s2, size_t n) {
207 return _strnicmp(s1, s2, n);
208}
209inline size_t asccpyn(char* buffer, size_t buflen,
210 const char* source, size_t srclen = SIZE_UNKNOWN) {
211 return strcpyn(buffer, buflen, source, srclen);
212}
213
214#if defined(WEBRTC_WIN)
215
216typedef wchar_t(*CharacterTransformation)(wchar_t);
217inline wchar_t identity(wchar_t c) { return c; }
218int ascii_string_compare(const wchar_t* s1, const char* s2, size_t n,
219 CharacterTransformation transformation);
220
221inline int asccmp(const wchar_t* s1, const char* s2) {
222 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), identity);
223}
224inline int ascicmp(const wchar_t* s1, const char* s2) {
225 return ascii_string_compare(s1, s2, static_cast<size_t>(-1), tolowercase);
226}
227inline int ascncmp(const wchar_t* s1, const char* s2, size_t n) {
228 return ascii_string_compare(s1, s2, n, identity);
229}
230inline int ascnicmp(const wchar_t* s1, const char* s2, size_t n) {
231 return ascii_string_compare(s1, s2, n, tolowercase);
232}
233size_t asccpyn(wchar_t* buffer, size_t buflen,
234 const char* source, size_t srclen = SIZE_UNKNOWN);
235
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200236#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200237
238///////////////////////////////////////////////////////////////////////////////
239// Traits<char> specializations
240///////////////////////////////////////////////////////////////////////////////
241
242template<>
243struct Traits<char> {
244 typedef std::string string;
245 inline static const char* empty_str() { return ""; }
246};
247
248///////////////////////////////////////////////////////////////////////////////
249// Traits<wchar_t> specializations (Windows only, currently)
250///////////////////////////////////////////////////////////////////////////////
251
252#if defined(WEBRTC_WIN)
253
254template<>
255struct Traits<wchar_t> {
256 typedef std::wstring string;
257 inline static const wchar_t* empty_str() { return L""; }
258};
259
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200260#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200261
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100262///////////////////////////////////////////////////////////////////////////////
263// UTF helpers (Windows only)
264///////////////////////////////////////////////////////////////////////////////
265
266#if defined(WEBRTC_WIN)
267
268inline std::wstring ToUtf16(const char* utf8, size_t len) {
269 int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len),
270 nullptr, 0);
271 wchar_t* ws = STACK_ARRAY(wchar_t, len16);
272 ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len), ws, len16);
273 return std::wstring(ws, len16);
274}
275
276inline std::wstring ToUtf16(const std::string& str) {
277 return ToUtf16(str.data(), str.length());
278}
279
280inline std::string ToUtf8(const wchar_t* wide, size_t len) {
281 int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len),
282 nullptr, 0, nullptr, nullptr);
283 char* ns = STACK_ARRAY(char, len8);
284 ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len), ns, len8,
285 nullptr, nullptr);
286 return std::string(ns, len8);
287}
288
289inline std::string ToUtf8(const wchar_t* wide) {
290 return ToUtf8(wide, wcslen(wide));
291}
292
293inline std::string ToUtf8(const std::wstring& wstr) {
294 return ToUtf8(wstr.data(), wstr.length());
295}
296
297#endif // WEBRTC_WIN
298
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200299// Replaces all occurrences of "search" with "replace".
300void replace_substrs(const char *search,
301 size_t search_len,
302 const char *replace,
303 size_t replace_len,
304 std::string *s);
305
306// True iff s1 starts with s2.
307bool starts_with(const char *s1, const char *s2);
308
309// True iff s1 ends with s2.
310bool ends_with(const char *s1, const char *s2);
311
312// Remove leading and trailing whitespaces.
313std::string string_trim(const std::string& s);
314
315} // namespace rtc
316
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200317#endif // RTC_BASE_STRINGUTILS_H_