Blender V5.0
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 <cstdarg>
6#include <cstdio>
7
8#include <algorithm>
9#include <cctype>
10
11#include "util/string.h"
12#include "util/types_float4.h"
13
14#ifdef _WIN32
15# include "util/windows.h"
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 (true) {
28 va_list args;
29 int result;
30
31 va_start(args, format);
32 result = vsnprintf(str.data(), 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 if (result >= (int)str.size()) {
46 /* not enough space */
47 str.resize(result + 1, 0);
48 continue;
49 }
50
51 return string(str.data());
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;
76 size_t token_length = 0;
77 for (size_t i = 0; i < str.size(); ++i) {
78 const char ch = str[i];
79 if (separators.find(ch) == string::npos) {
80 /* Current character is not a separator,
81 * append it to token by increasing token length.
82 */
83 ++token_length;
84 }
85 else {
86 /* Current character is a separator,
87 * append current token to the list.
88 */
89 if (!skip_empty_tokens || token_length > 0) {
90 const string token = str.substr(token_start, token_length);
91 tokens.push_back(token);
92 }
93 token_start = i + 1;
94 token_length = 0;
95 }
96 }
97 /* Append token from the tail of the string if exists. */
98 if (token_length) {
99 const string token = str.substr(token_start, token_length);
100 tokens.push_back(token);
101 }
102}
103
104bool string_startswith(const string_view s, const string_view start)
105{
106 const size_t len = start.size();
107 if (len > s.size()) {
108 return false;
109 }
110
111 for (size_t i = 0; i < len; i++) {
112 if (s[i] != start[i]) {
113 return false;
114 }
115 }
116
117 return true;
118}
119
120bool string_endswith(const string_view s, const string_view end)
121{
122 const size_t len = end.size();
123 if (len > s.size()) {
124 return false;
125 }
126
127 const size_t offset = s.size() - len;
128 for (size_t i = 0; i < len; i++) {
129 if (s[offset + i] != end[i]) {
130 return false;
131 }
132 }
133
134 return true;
135}
136
137string string_strip(const string &s)
138{
139 string result = s;
140 result.erase(0, result.find_first_not_of(' '));
141 result.erase(result.find_last_not_of(' ') + 1);
142 return result;
143}
144
145void string_replace(string &haystack, const string &needle, const string &other)
146{
147 size_t i = 0;
148 size_t index;
149 while ((index = haystack.find(needle, i)) != string::npos) {
150 haystack.replace(index, needle.size(), other);
151 i = index + other.size();
152 }
153}
154
155void string_replace_same_length(string &haystack, const string &needle, const string &other)
156{
157 assert(needle.size() == other.size());
158 size_t pos = 0;
159 while (pos != string::npos) {
160 pos = haystack.find(needle, pos);
161 if (pos != string::npos) {
162 memcpy(haystack.data() + pos, other.data(), other.size());
163 pos += other.size();
164 }
165 }
166}
167
168string string_remove_trademark(const string &s)
169{
170 string result = s;
171
172 /* Special case, so we don't leave sequential spaces behind. */
173 /* TODO(sergey): Consider using regex perhaps? */
174 string_replace(result, " (TM)", "");
175 string_replace(result, " (R)", "");
176
177 string_replace(result, "(TM)", "");
178 string_replace(result, "(R)", "");
179
180 return string_strip(result);
181}
182
183string string_from_bool(bool var)
184{
185 if (var) {
186 return "True";
187 }
188 return "False";
189}
190
191string string_hex(const uint8_t *data, const size_t size)
192{
193 string result;
194 for (size_t i = 0; i < size; i++) {
195 result += string_printf("%x", data[i]);
196 }
197 return result;
198}
199
200string to_string(const char *str)
201{
202 return string(str);
203}
204
205string to_string(const float4 &v)
206{
207 return string_printf("%f,%f,%f,%f", v.x, v.y, v.z, v.w);
208}
209
210string string_to_lower(const string &s)
211{
212 string r = s;
213 std::transform(r.begin(), r.end(), r.begin(), [](char c) { return std::tolower(c); });
214 return r;
215}
216
217/* Wide char strings helpers for Windows. */
218
219#ifdef _WIN32
220
221wstring string_to_wstring(const string &str)
222{
223 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), nullptr, 0);
224 wstring str_wc(length_wc, 0);
225 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
226 return str_wc;
227}
228
229string string_from_wstring(const wstring &str)
230{
231 int length_mb = WideCharToMultiByte(
232 CP_UTF8, 0, str.c_str(), str.size(), nullptr, 0, nullptr, nullptr);
233 string str_mb(length_mb, 0);
234 WideCharToMultiByte(
235 CP_UTF8, 0, str.c_str(), str.size(), &str_mb[0], length_mb, nullptr, nullptr);
236 return str_mb;
237}
238
239string string_to_ansi(const string &str)
240{
241 const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), nullptr, 0);
242 wstring str_wc(length_wc, 0);
243 MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
244
245 int length_mb = WideCharToMultiByte(
246 CP_ACP, 0, str_wc.c_str(), str_wc.size(), nullptr, 0, nullptr, nullptr);
247
248 string str_mb(length_mb, 0);
249 WideCharToMultiByte(
250 CP_ACP, 0, str_wc.c_str(), str_wc.size(), &str_mb[0], length_mb, nullptr, nullptr);
251
252 return str_mb;
253}
254
255#endif /* _WIN32 */
256
258{
259 static const char suffixes[] = "BKMGTPEZY";
260
261 const char *suffix = suffixes;
262 size_t r = 0;
263
264 while (size >= 1024) {
265 r = size % 1024;
266 size /= 1024;
267 suffix++;
268 }
269
270 if (*suffix != 'B') {
271 return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
272 }
273 return string_printf("%zu", size);
274}
275
277{
278 if (num == 0) {
279 return "0";
280 }
281
282 /* Add thousands separators. */
283 char buf[32];
284
285 char *p = buf + 31;
286 *p = '\0';
287
288 int i = -1;
289 while (num) {
290 i++;
291 if (i && i % 3 == 0) {
292 *(--p) = ',';
293 }
294
295 *(--p) = '0' + (num % 10);
296
297 num /= 10;
298 }
299
300 return p;
301}
302
ATTR_WARN_UNUSED_RESULT const size_t num
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
#define CCL_NAMESPACE_END
#define str(s)
uint pos
#define assert(assertion)
format
string string_remove_trademark(const string &s)
Definition string.cpp:168
string string_from_bool(bool var)
Definition string.cpp:183
string string_human_readable_size(size_t size)
Definition string.cpp:257
bool string_iequals(const string &a, const string &b)
Definition string.cpp:55
string string_strip(const string &s)
Definition string.cpp:137
string to_string(const char *str)
Definition string.cpp:200
string string_hex(const uint8_t *data, const size_t size)
Definition string.cpp:191
string string_human_readable_number(size_t num)
Definition string.cpp:276
bool string_startswith(const string_view s, const string_view start)
Definition string.cpp:104
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:155
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:145
bool string_endswith(const string_view s, const string_view end)
Definition string.cpp:120
string string_to_lower(const string &s)
Definition string.cpp:210
i
Definition text_draw.cc:230
uint len