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 if (len > s.size()) {
107 return false;
108 }
109
110 for (size_t i = 0; i < len; i++) {
111 if (s[i] != start[i]) {
112 return false;
113 }
114 }
115
116 return true;
117}
118
119bool string_endswith(const string_view s, const string_view end)
120{
121 const size_t len = end.size();
122 if (len > s.size()) {
123 return false;
124 }
125
126 const size_t offset = s.size() - len;
127 for (size_t i = 0; i < len; i++) {
128 if (s[offset + i] != end[i]) {
129 return false;
130 }
131 }
132
133 return true;
134}
135
136string string_strip(const string &s)
137{
138 string result = s;
139 result.erase(0, result.find_first_not_of(' '));
140 result.erase(result.find_last_not_of(' ') + 1);
141 return result;
142}
143
144void string_replace(string &haystack, const string &needle, const string &other)
145{
146 size_t i = 0, index;
147 while ((index = haystack.find(needle, i)) != string::npos) {
148 haystack.replace(index, needle.size(), other);
149 i = index + other.size();
150 }
151}
152
153void string_replace_same_length(string &haystack, const string &needle, const string &other)
154{
155 assert(needle.size() == other.size());
156 size_t pos = 0;
157 while (pos != string::npos) {
158 pos = haystack.find(needle, pos);
159 if (pos != string::npos) {
160 memcpy(haystack.data() + pos, other.data(), other.size());
161 pos += other.size();
162 }
163 }
164}
165
166string string_remove_trademark(const string &s)
167{
168 string result = s;
169
170 /* Special case, so we don't leave sequential spaces behind. */
171 /* TODO(sergey): Consider using regex perhaps? */
172 string_replace(result, " (TM)", "");
173 string_replace(result, " (R)", "");
174
175 string_replace(result, "(TM)", "");
176 string_replace(result, "(R)", "");
177
178 return string_strip(result);
179}
180
181string string_from_bool(bool var)
182{
183 if (var) {
184 return "True";
185 }
186 else {
187 return "False";
188 }
189}
190
191string to_string(const char *str)
192{
193 return string(str);
194}
195
196string to_string(const float4 &v)
197{
198 return string_printf("%f,%f,%f,%f", v.x, v.y, v.z, v.w);
199}
200
201string string_to_lower(const string &s)
202{
203 string r = s;
204 std::transform(r.begin(), r.end(), r.begin(), [](char c) { return std::tolower(c); });
205 return r;
206}
207
208/* Wide char strings helpers for Windows. */
209
210#ifdef _WIN32
211
212wstring string_to_wstring(const string &str)
213{
214 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
215 wstring str_wc(length_wc, 0);
216 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
217 return str_wc;
218}
219
220string string_from_wstring(const wstring &str)
221{
222 int length_mb = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
223 string str_mb(length_mb, 0);
224 WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), &str_mb[0], length_mb, NULL, NULL);
225 return str_mb;
226}
227
228string string_to_ansi(const string &str)
229{
230 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
231 wstring str_wc(length_wc, 0);
232 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
233
234 int length_mb = WideCharToMultiByte(
235 CP_ACP, 0, str_wc.c_str(), str_wc.size(), NULL, 0, NULL, NULL);
236
237 string str_mb(length_mb, 0);
238 WideCharToMultiByte(CP_ACP, 0, str_wc.c_str(), str_wc.size(), &str_mb[0], length_mb, NULL, NULL);
239
240 return str_mb;
241}
242
243#endif /* _WIN32 */
244
246{
247 static const char suffixes[] = "BKMGTPEZY";
248
249 const char *suffix = suffixes;
250 size_t r = 0;
251
252 while (size >= 1024) {
253 r = size % 1024;
254 size /= 1024;
255 suffix++;
256 }
257
258 if (*suffix != 'B') {
259 return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
260 }
261 else {
262 return string_printf("%zu", size);
263 }
264}
265
267{
268 if (num == 0) {
269 return "0";
270 }
271
272 /* Add thousands separators. */
273 char buf[32];
274
275 char *p = buf + 31;
276 *p = '\0';
277
278 int i = -1;
279 while (num) {
280 if (++i && i % 3 == 0) {
281 *(--p) = ',';
282 }
283
284 *(--p) = '0' + (num % 10);
285
286 num /= 10;
287 }
288
289 return p;
290}
291
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
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:166
string string_from_bool(bool var)
Definition string.cpp:181
string string_human_readable_size(size_t size)
Definition string.cpp:245
bool string_iequals(const string &a, const string &b)
Definition string.cpp:55
string string_strip(const string &s)
Definition string.cpp:136
string to_string(const char *str)
Definition string.cpp:191
string string_human_readable_number(size_t num)
Definition string.cpp:266
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:153
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:144
bool string_endswith(const string_view s, const string_view end)
Definition string.cpp:119
string string_to_lower(const string &s)
Definition string.cpp:201
VecBase< float, 4 > float4