blob: 2d9228b70474ff62886fff44fa225e1c02a9598e [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
Yves Gerey665174f2018-06-19 15:03:05 +020040#define STACK_ARRAY(TYPE, LEN) \
41 static_cast<TYPE*>(::alloca((LEN) * sizeof(TYPE)))
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020042
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020043
44#if defined(WEBRTC_POSIX)
45
46inline int _stricmp(const char* s1, const char* s2) {
47 return strcasecmp(s1, s2);
48}
49inline int _strnicmp(const char* s1, const char* s2, size_t n) {
50 return strncasecmp(s1, s2, n);
51}
52
Jonas Olsson74395342018-04-03 12:22:07 +020053#endif // WEBRTC_POSIX
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020054
55///////////////////////////////////////////////////////////////////////////////
56// Traits simplifies porting string functions to be CTYPE-agnostic
57///////////////////////////////////////////////////////////////////////////////
58
59namespace rtc {
60
61const size_t SIZE_UNKNOWN = static_cast<size_t>(-1);
62
Yves Gerey665174f2018-06-19 15:03:05 +020063template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020064struct Traits {
65 // STL string type
Jonas Olsson74395342018-04-03 12:22:07 +020066 // typedef XXX string;
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020067 // Null-terminated string
Jonas Olsson74395342018-04-03 12:22:07 +020068 // inline static const CTYPE* empty_str();
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020069};
70
71///////////////////////////////////////////////////////////////////////////////
72// String utilities which work with char or wchar_t
73///////////////////////////////////////////////////////////////////////////////
74
75template <class CTYPE>
76inline const CTYPE* nonnull(const CTYPE* str, const CTYPE* def_str = nullptr) {
77 return str ? str : (def_str ? def_str : Traits<CTYPE>::empty_str());
78}
79
Yves Gerey665174f2018-06-19 15:03:05 +020080template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020081const CTYPE* strchr(const CTYPE* str, const CTYPE* chs) {
Yves Gerey665174f2018-06-19 15:03:05 +020082 for (size_t i = 0; str[i]; ++i) {
83 for (size_t j = 0; chs[j]; ++j) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020084 if (str[i] == chs[j]) {
85 return str + i;
86 }
87 }
88 }
89 return 0;
90}
91
Yves Gerey665174f2018-06-19 15:03:05 +020092template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020093const CTYPE* strchrn(const CTYPE* str, size_t slen, CTYPE ch) {
Yves Gerey665174f2018-06-19 15:03:05 +020094 for (size_t i = 0; i < slen && str[i]; ++i) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +020095 if (str[i] == ch) {
96 return str + i;
97 }
98 }
99 return 0;
100}
101
Yves Gerey665174f2018-06-19 15:03:05 +0200102template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200103size_t strlenn(const CTYPE* buffer, size_t buflen) {
104 size_t bufpos = 0;
105 while (buffer[bufpos] && (bufpos < buflen)) {
106 ++bufpos;
107 }
108 return bufpos;
109}
110
111// Safe versions of strncpy, strncat, snprintf and vsnprintf that always
112// null-terminate.
113
Yves Gerey665174f2018-06-19 15:03:05 +0200114template <class CTYPE>
115size_t strcpyn(CTYPE* buffer,
116 size_t buflen,
117 const CTYPE* source,
118 size_t srclen = SIZE_UNKNOWN) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200119 if (buflen <= 0)
120 return 0;
121
122 if (srclen == SIZE_UNKNOWN) {
123 srclen = strlenn(source, buflen - 1);
124 } else if (srclen >= buflen) {
125 srclen = buflen - 1;
126 }
127 memcpy(buffer, source, srclen * sizeof(CTYPE));
128 buffer[srclen] = 0;
129 return srclen;
130}
131
Yves Gerey665174f2018-06-19 15:03:05 +0200132template <class CTYPE>
133size_t strcatn(CTYPE* buffer,
134 size_t buflen,
135 const CTYPE* source,
136 size_t srclen = SIZE_UNKNOWN) {
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200137 if (buflen <= 0)
138 return 0;
139
140 size_t bufpos = strlenn(buffer, buflen - 1);
141 return bufpos + strcpyn(buffer + bufpos, buflen - bufpos, source, srclen);
142}
143
144// Some compilers (clang specifically) require vsprintfn be defined before
145// sprintfn.
Yves Gerey665174f2018-06-19 15:03:05 +0200146template <class CTYPE>
147size_t vsprintfn(CTYPE* buffer,
148 size_t buflen,
149 const CTYPE* format,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200150 va_list args) {
151 int len = vsnprintf(buffer, buflen, format, args);
152 if ((len < 0) || (static_cast<size_t>(len) >= buflen)) {
153 len = static_cast<int>(buflen - 1);
154 buffer[len] = 0;
155 }
156 return len;
157}
158
Yves Gerey665174f2018-06-19 15:03:05 +0200159template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200160size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...);
Yves Gerey665174f2018-06-19 15:03:05 +0200161template <class CTYPE>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200162size_t sprintfn(CTYPE* buffer, size_t buflen, const CTYPE* format, ...) {
163 va_list args;
164 va_start(args, format);
165 size_t len = vsprintfn(buffer, buflen, format, args);
166 va_end(args);
167 return len;
168}
169
170///////////////////////////////////////////////////////////////////////////////
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200171// Traits<char> specializations
172///////////////////////////////////////////////////////////////////////////////
173
Yves Gerey665174f2018-06-19 15:03:05 +0200174template <>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200175struct Traits<char> {
176 typedef std::string string;
177 inline static const char* empty_str() { return ""; }
178};
179
180///////////////////////////////////////////////////////////////////////////////
181// Traits<wchar_t> specializations (Windows only, currently)
182///////////////////////////////////////////////////////////////////////////////
183
184#if defined(WEBRTC_WIN)
185
Yves Gerey665174f2018-06-19 15:03:05 +0200186template <>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200187struct Traits<wchar_t> {
188 typedef std::wstring string;
189 inline static const wchar_t* empty_str() { return L""; }
190};
191
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200192#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200193
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100194///////////////////////////////////////////////////////////////////////////////
195// UTF helpers (Windows only)
196///////////////////////////////////////////////////////////////////////////////
197
198#if defined(WEBRTC_WIN)
199
200inline std::wstring ToUtf16(const char* utf8, size_t len) {
201 int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len),
202 nullptr, 0);
203 wchar_t* ws = STACK_ARRAY(wchar_t, len16);
204 ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len), ws, len16);
205 return std::wstring(ws, len16);
206}
207
208inline std::wstring ToUtf16(const std::string& str) {
209 return ToUtf16(str.data(), str.length());
210}
211
212inline std::string ToUtf8(const wchar_t* wide, size_t len) {
213 int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len),
214 nullptr, 0, nullptr, nullptr);
215 char* ns = STACK_ARRAY(char, len8);
216 ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len), ns, len8,
217 nullptr, nullptr);
218 return std::string(ns, len8);
219}
220
221inline std::string ToUtf8(const wchar_t* wide) {
222 return ToUtf8(wide, wcslen(wide));
223}
224
225inline std::string ToUtf8(const std::wstring& wstr) {
226 return ToUtf8(wstr.data(), wstr.length());
227}
228
229#endif // WEBRTC_WIN
230
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200231// Replaces all occurrences of "search" with "replace".
Yves Gerey665174f2018-06-19 15:03:05 +0200232void replace_substrs(const char* search,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200233 size_t search_len,
Yves Gerey665174f2018-06-19 15:03:05 +0200234 const char* replace,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200235 size_t replace_len,
Yves Gerey665174f2018-06-19 15:03:05 +0200236 std::string* s);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200237
238// True iff s1 starts with s2.
Yves Gerey665174f2018-06-19 15:03:05 +0200239bool starts_with(const char* s1, const char* s2);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200240
241// True iff s1 ends with s2.
Yves Gerey665174f2018-06-19 15:03:05 +0200242bool ends_with(const char* s1, const char* s2);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200243
244// Remove leading and trailing whitespaces.
245std::string string_trim(const std::string& s);
246
Jonas Olssonabbe8412018-04-03 13:40:05 +0200247// TODO(jonasolsson): replace with absl::Hex when that becomes available.
Jonas Olsson74395342018-04-03 12:22:07 +0200248std::string ToHex(const int i);
Jonas Olssond8c50782018-09-07 11:21:28 +0200249
250std::string LeftPad(char padding, unsigned length, std::string s);
251
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200252} // namespace rtc
253
Jonas Olsson74395342018-04-03 12:22:07 +0200254#endif // RTC_BASE_STRINGUTILS_H_