Blender V4.3
string.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <stdarg.h>
6#include <stdio.h>
7
8#include <algorithm>
9#include <cctype>
10
11#include "util/foreach.h"
12#include "util/string.h"
13#include "util/windows.h"
14
15#ifdef _WIN32
16# ifndef vsnprintf
17# define vsnprintf _vsnprintf
18# endif
19#endif /* _WIN32 */
20
22
23string string_printf(const char *format, ...)
24{
25 vector<char> str(128, 0);
26
27 while (1) {
28 va_list args;
29 int result;
30
31 va_start(args, format);
32 result = vsnprintf(&str[0], str.size(), format, args);
33 va_end(args);
34
35 if (result == -1) {
36 /* not enough space or formatting error */
37 if (str.size() > 65536) {
38 assert(0);
39 return string("");
40 }
41
42 str.resize(str.size() * 2, 0);
43 continue;
44 }
45 else if (result >= (int)str.size()) {
46 /* not enough space */
47 str.resize(result + 1, 0);
48 continue;
49 }
50
51 return string(&str[0]);
52 }
53}
54
55bool string_iequals(const string &a, const string &b)
56{
57 if (a.size() == b.size()) {
58 for (size_t i = 0; i < a.size(); i++) {
59 if (toupper(a[i]) != toupper(b[i])) {
60 return false;
61 }
62 }
63
64 return true;
65 }
66
67 return false;
68}
69
71 const string &str,
72 const string &separators,
73 bool skip_empty_tokens)
74{
75 size_t token_start = 0, token_length = 0;
76 for (size_t i = 0; i < str.size(); ++i) {
77 const char ch = str[i];
78 if (separators.find(ch) == string::npos) {
79 /* Current character is not a separator,
80 * append it to token by increasing token length.
81 */
82 ++token_length;
83 }
84 else {
85 /* Current character is a separator,
86 * append current token to the list.
87 */
88 if (!skip_empty_tokens || token_length > 0) {
89 string token = str.substr(token_start, token_length);
90 tokens.push_back(token);
91 }
92 token_start = i + 1;
93 token_length = 0;
94 }
95 }
96 /* Append token from the tail of the string if exists. */
97 if (token_length) {
98 string token = str.substr(token_start, token_length);
99 tokens.push_back(token);
100 }
101}
102
103bool string_startswith(const string_view s, const string_view start)
104{
105 const size_t len = start.size();
106
107 if (len > s.size()) {
108 return false;
109 }
110
111 return strncmp(s.c_str(), start.data(), len) == 0;
112}
113
114bool string_endswith(const string_view s, const string_view end)
115{
116 const size_t len = end.size();
117
118 if (len > s.size()) {
119 return false;
120 }
121
122 return strncmp(s.c_str() + s.size() - len, end.data(), len) == 0;
123}
124
125string string_strip(const string &s)
126{
127 string result = s;
128 result.erase(0, result.find_first_not_of(' '));
129 result.erase(result.find_last_not_of(' ') + 1);
130 return result;
131}
132
133void string_replace(string &haystack, const string &needle, const string &other)
134{
135 size_t i = 0, index;
136 while ((index = haystack.find(needle, i)) != string::npos) {
137 haystack.replace(index, needle.size(), other);
138 i = index + other.size();
139 }
140}
141
142void string_replace_same_length(string &haystack, const string &needle, const string &other)
143{
144 assert(needle.size() == other.size());
145 size_t pos = 0;
146 while (pos != string::npos) {
147 pos = haystack.find(needle, pos);
148 if (pos != string::npos) {
149 memcpy(haystack.data() + pos, other.data(), other.size());
150 pos += other.size();
151 }
152 }
153}
154
155string string_remove_trademark(const string &s)
156{
157 string result = s;
158
159 /* Special case, so we don't leave sequential spaces behind. */
160 /* TODO(sergey): Consider using regex perhaps? */
161 string_replace(result, " (TM)", "");
162 string_replace(result, " (R)", "");
163
164 string_replace(result, "(TM)", "");
165 string_replace(result, "(R)", "");
166
167 return string_strip(result);
168}
169
170string string_from_bool(bool var)
171{
172 if (var) {
173 return "True";
174 }
175 else {
176 return "False";
177 }
178}
179
180string to_string(const char *str)
181{
182 return string(str);
183}
184
185string to_string(const float4 &v)
186{
187 return string_printf("%f,%f,%f,%f", v.x, v.y, v.z, v.w);
188}
189
190string string_to_lower(const string &s)
191{
192 string r = s;
193 std::transform(r.begin(), r.end(), r.begin(), [](char c) { return std::tolower(c); });
194 return r;
195}
196
197/* Wide char strings helpers for Windows. */
198
199#ifdef _WIN32
200
201wstring string_to_wstring(const string &str)
202{
203 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
204 wstring str_wc(length_wc, 0);
205 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
206 return str_wc;
207}
208
209string string_from_wstring(const wstring &str)
210{
211 int length_mb = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
212 string str_mb(length_mb, 0);
213 WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), &str_mb[0], length_mb, NULL, NULL);
214 return str_mb;
215}
216
217string string_to_ansi(const string &str)
218{
219 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
220 wstring str_wc(length_wc, 0);
221 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
222
223 int length_mb = WideCharToMultiByte(
224 CP_ACP, 0, str_wc.c_str(), str_wc.size(), NULL, 0, NULL, NULL);
225
226 string str_mb(length_mb, 0);
227 WideCharToMultiByte(CP_ACP, 0, str_wc.c_str(), str_wc.size(), &str_mb[0], length_mb, NULL, NULL);
228
229 return str_mb;
230}
231
232#endif /* _WIN32 */
233
234string string_human_readable_size(size_t size)
235{
236 static const char suffixes[] = "BKMGTPEZY";
237
238 const char *suffix = suffixes;
239 size_t r = 0;
240
241 while (size >= 1024) {
242 r = size % 1024;
243 size /= 1024;
244 suffix++;
245 }
246
247 if (*suffix != 'B') {
248 return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
249 }
250 else {
251 return string_printf("%zu", size);
252 }
253}
254
256{
257 if (num == 0) {
258 return "0";
259 }
260
261 /* Add thousands separators. */
262 char buf[32];
263
264 char *p = buf + 31;
265 *p = '\0';
266
267 int i = -1;
268 while (num) {
269 if (++i && i % 3 == 0) {
270 *(--p) = ',';
271 }
272
273 *(--p) = '0' + (num % 10);
274
275 num /= 10;
276 }
277
278 return p;
279}
280
ATTR_WARN_UNUSED_RESULT const BMVert * v
local_group_size(16, 16) .push_constant(Type b
#define CCL_NAMESPACE_END
#define NULL
int len
#define str(s)
format
string string_remove_trademark(const string &s)
Definition string.cpp:155
string string_from_bool(bool var)
Definition string.cpp:170
string string_human_readable_size(size_t size)
Definition string.cpp:234
bool string_iequals(const string &a, const string &b)
Definition string.cpp:55
string string_strip(const string &s)
Definition string.cpp:125
string to_string(const char *str)
Definition string.cpp:180
string string_human_readable_number(size_t num)
Definition string.cpp:255
bool string_startswith(const string_view s, const string_view start)
Definition string.cpp:103
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
void string_replace_same_length(string &haystack, const string &needle, const string &other)
Definition string.cpp:142
void string_split(vector< string > &tokens, const string &str, const string &separators, bool skip_empty_tokens)
Definition string.cpp:70
void string_replace(string &haystack, const string &needle, const string &other)
Definition string.cpp:133
bool string_endswith(const string_view s, const string_view end)
Definition string.cpp:114
string string_to_lower(const string &s)
Definition string.cpp:190