blob: 75436b19cdc03345e482985db7353622a4ff5703 [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
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200144///////////////////////////////////////////////////////////////////////////////
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200145// Traits<char> specializations
146///////////////////////////////////////////////////////////////////////////////
147
Yves Gerey665174f2018-06-19 15:03:05 +0200148template <>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200149struct Traits<char> {
150 typedef std::string string;
151 inline static const char* empty_str() { return ""; }
152};
153
154///////////////////////////////////////////////////////////////////////////////
155// Traits<wchar_t> specializations (Windows only, currently)
156///////////////////////////////////////////////////////////////////////////////
157
158#if defined(WEBRTC_WIN)
159
Yves Gerey665174f2018-06-19 15:03:05 +0200160template <>
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200161struct Traits<wchar_t> {
162 typedef std::wstring string;
163 inline static const wchar_t* empty_str() { return L""; }
164};
165
Henrik Kjellanderc0362762017-06-29 08:03:04 +0200166#endif // WEBRTC_WIN
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200167
Patrik Höglunda8005cf2017-12-13 16:05:42 +0100168///////////////////////////////////////////////////////////////////////////////
169// UTF helpers (Windows only)
170///////////////////////////////////////////////////////////////////////////////
171
172#if defined(WEBRTC_WIN)
173
174inline std::wstring ToUtf16(const char* utf8, size_t len) {
175 int len16 = ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len),
176 nullptr, 0);
177 wchar_t* ws = STACK_ARRAY(wchar_t, len16);
178 ::MultiByteToWideChar(CP_UTF8, 0, utf8, static_cast<int>(len), ws, len16);
179 return std::wstring(ws, len16);
180}
181
182inline std::wstring ToUtf16(const std::string& str) {
183 return ToUtf16(str.data(), str.length());
184}
185
186inline std::string ToUtf8(const wchar_t* wide, size_t len) {
187 int len8 = ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len),
188 nullptr, 0, nullptr, nullptr);
189 char* ns = STACK_ARRAY(char, len8);
190 ::WideCharToMultiByte(CP_UTF8, 0, wide, static_cast<int>(len), ns, len8,
191 nullptr, nullptr);
192 return std::string(ns, len8);
193}
194
195inline std::string ToUtf8(const wchar_t* wide) {
196 return ToUtf8(wide, wcslen(wide));
197}
198
199inline std::string ToUtf8(const std::wstring& wstr) {
200 return ToUtf8(wstr.data(), wstr.length());
201}
202
203#endif // WEBRTC_WIN
204
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200205// Replaces all occurrences of "search" with "replace".
Yves Gerey665174f2018-06-19 15:03:05 +0200206void replace_substrs(const char* search,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200207 size_t search_len,
Yves Gerey665174f2018-06-19 15:03:05 +0200208 const char* replace,
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200209 size_t replace_len,
Yves Gerey665174f2018-06-19 15:03:05 +0200210 std::string* s);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200211
212// True iff s1 starts with s2.
Yves Gerey665174f2018-06-19 15:03:05 +0200213bool starts_with(const char* s1, const char* s2);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200214
215// True iff s1 ends with s2.
Yves Gerey665174f2018-06-19 15:03:05 +0200216bool ends_with(const char* s1, const char* s2);
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200217
218// Remove leading and trailing whitespaces.
219std::string string_trim(const std::string& s);
220
Jonas Olssonabbe8412018-04-03 13:40:05 +0200221// TODO(jonasolsson): replace with absl::Hex when that becomes available.
Jonas Olsson74395342018-04-03 12:22:07 +0200222std::string ToHex(const int i);
Jonas Olssond8c50782018-09-07 11:21:28 +0200223
224std::string LeftPad(char padding, unsigned length, std::string s);
225
Henrik Kjellanderec78f1c2017-06-29 07:52:50 +0200226} // namespace rtc
227
Jonas Olsson74395342018-04-03 12:22:07 +0200228#endif // RTC_BASE_STRINGUTILS_H_