Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenlib / intern / string_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2017 by the Blender FOundation.
19  * All rights reserved.
20  *
21  * Contributor(s): none yet.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  * 
25  */
26
27 /** \file blender/blenlib/intern/string_utils.c
28  *  \ingroup bli
29  */
30
31 #include <ctype.h>
32 #include <string.h>
33 #include <stdlib.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_listbase.h"
38 #include "BLI_string.h"
39 #include "BLI_string_utf8.h"
40 #include "BLI_string_utils.h"
41 #include "BLI_utildefines.h"
42
43 #include "DNA_listBase.h"
44
45
46 #ifdef __GNUC__
47 #  pragma GCC diagnostic error "-Wsign-conversion"
48 #endif
49
50 /**
51  * Looks for a numeric suffix preceded by delim character on the end of
52  * name, puts preceding part into *left and value of suffix into *nr.
53  * Returns the length of *left.
54  *
55  * Foo.001 -> "Foo", 1
56  * Returning the length of "Foo"
57  *
58  * \param left  Where to return copy of part preceding delim
59  * \param nr  Where to return value of numeric suffix
60  * \param name  String to split
61  * \param delim  Delimiter character
62  * \return  Length of \a left
63  */
64 size_t BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
65 {
66         const size_t name_len = strlen(name);
67
68         *nr = 0;
69         memcpy(left, name, (name_len + 1) * sizeof(char));
70
71         /* name doesn't end with a delimiter "foo." */
72         if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
73                 size_t a = name_len;
74                 while (a--) {
75                         if (name[a] == delim) {
76                                 left[a] = '\0';  /* truncate left part here */
77                                 *nr = atol(name + a + 1);
78                                 /* casting down to an int, can overflow for large numbers */
79                                 if (*nr < 0)
80                                         *nr = 0;
81                                 return a;
82                         }
83                         else if (isdigit(name[a]) == 0) {
84                                 /* non-numeric suffix - give up */
85                                 break;
86                         }
87                 }
88         }
89
90         return name_len;
91 }
92
93 static bool is_char_sep(const char c)
94 {
95         return ELEM(c, '.', ' ', '-', '_');
96 }
97
98 /**
99  * based on `BLI_split_dirfile()` / `os.path.splitext()`,
100  * `"a.b.c"` -> (`"a.b"`, `".c"`).
101  */
102 void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len)
103 {
104         size_t len = BLI_strnlen(string, str_len);
105         size_t i;
106
107         r_body[0] = r_suf[0] = '\0';
108
109         for (i = len; i > 0; i--) {
110                 if (is_char_sep(string[i])) {
111                         BLI_strncpy(r_body, string, i + 1);
112                         BLI_strncpy(r_suf, string + i,  (len + 1) - i);
113                         return;
114                 }
115         }
116
117         memcpy(r_body, string, len + 1);
118 }
119
120 /**
121  * `"a.b.c"` -> (`"a."`, `"b.c"`)
122  */
123 void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len)
124 {
125         size_t len = BLI_strnlen(string, str_len);
126         size_t i;
127
128         r_body[0] = r_pre[0] = '\0';
129
130         for (i = 1; i < len; i++) {
131                 if (is_char_sep(string[i])) {
132                         i++;
133                         BLI_strncpy(r_pre, string, i + 1);
134                         BLI_strncpy(r_body, string + i, (len + 1) - i);
135                         return;
136                 }
137         }
138
139         BLI_strncpy(r_body, string, len);
140 }
141
142 /**
143  * Finds the best possible flipped (left/right) name. For renaming; check for unique names afterwards.
144  *
145  * \param r_name flipped name, assumed to be a pointer to a string of at least \a name_len size.
146  * \param from_name original name, assumed to be a pointer to a string of at least \a name_len size.
147  * \param strip_number If set, remove number extensions.
148  */
149 void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len)
150 {
151         size_t len;
152         char *prefix  = alloca(name_len);   /* The part before the facing */
153         char *suffix  = alloca(name_len);   /* The part after the facing */
154         char *replace = alloca(name_len);   /* The replacement string */
155         char *number  = alloca(name_len);   /* The number extension string */
156         char *index = NULL;
157         bool is_set = false;
158
159         *prefix = *suffix = *replace = *number = '\0';
160
161         /* always copy the name, since this can be called with an uninitialized string */
162         BLI_strncpy(r_name, from_name, name_len);
163
164         len = BLI_strnlen(from_name, name_len);
165         if (len < 3) {
166                 /* we don't do names like .R or .L */
167                 return;
168         }
169
170         /* We first check the case with a .### extension, let's find the last period */
171         if (isdigit(r_name[len - 1])) {
172                 index = strrchr(r_name, '.'); // last occurrence
173                 if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever!
174                         if (strip_number == false) {
175                                 BLI_strncpy(number, index, name_len);
176                         }
177                         *index = 0;
178                         len = BLI_strnlen(r_name, name_len);
179                 }
180         }
181
182         BLI_strncpy(prefix, r_name, name_len);
183
184         /* first case; separator . - _ with extensions r R l L  */
185         if ((len > 1) && is_char_sep(r_name[len - 2])) {
186                 is_set = true;
187                 switch (r_name[len - 1]) {
188                         case 'l':
189                                 prefix[len - 1] = 0;
190                                 strcpy(replace, "r");
191                                 break;
192                         case 'r':
193                                 prefix[len - 1] = 0;
194                                 strcpy(replace, "l");
195                                 break;
196                         case 'L':
197                                 prefix[len - 1] = 0;
198                                 strcpy(replace, "R");
199                                 break;
200                         case 'R':
201                                 prefix[len - 1] = 0;
202                                 strcpy(replace, "L");
203                                 break;
204                         default:
205                                 is_set = false;
206                 }
207         }
208
209         /* case; beginning with r R l L, with separator after it */
210         if (!is_set && is_char_sep(r_name[1])) {
211                 is_set = true;
212                 switch (r_name[0]) {
213                         case 'l':
214                                 strcpy(replace, "r");
215                                 BLI_strncpy(suffix, r_name + 1, name_len);
216                                 prefix[0] = 0;
217                                 break;
218                         case 'r':
219                                 strcpy(replace, "l");
220                                 BLI_strncpy(suffix, r_name + 1, name_len);
221                                 prefix[0] = 0;
222                                 break;
223                         case 'L':
224                                 strcpy(replace, "R");
225                                 BLI_strncpy(suffix, r_name + 1, name_len);
226                                 prefix[0] = 0;
227                                 break;
228                         case 'R':
229                                 strcpy(replace, "L");
230                                 BLI_strncpy(suffix, r_name + 1, name_len);
231                                 prefix[0] = 0;
232                                 break;
233                         default:
234                                 is_set = false;
235                 }
236         }
237
238         if (!is_set && len > 5) {
239                 /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */
240                 if (((index = BLI_strcasestr(prefix, "right")) == prefix) ||
241                     (index == prefix + len - 5))
242                 {
243                         is_set = true;
244                         if (index[0] == 'r') {
245                                 strcpy(replace, "left");
246                         }
247                         else {
248                                 strcpy(replace, (index[1] == 'I') ? "LEFT" : "Left");
249                         }
250                         *index = 0;
251                         BLI_strncpy(suffix, index + 5, name_len);
252                 }
253                 else if (((index = BLI_strcasestr(prefix, "left")) == prefix) ||
254                          (index == prefix + len - 4))
255                 {
256                         is_set = true;
257                         if (index[0] == 'l') {
258                                 strcpy(replace, "right");
259                         }
260                         else {
261                                 strcpy(replace, (index[1] == 'E') ? "RIGHT" : "Right");
262                         }
263                         *index = 0;
264                         BLI_strncpy(suffix, index + 4, name_len);
265                 }
266         }
267
268         BLI_snprintf(r_name, name_len, "%s%s%s%s", prefix, replace, suffix, number);
269 }
270
271
272 /* Unique name utils. */
273
274 /**
275  * Ensures name is unique (according to criteria specified by caller in unique_check callback),
276  * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
277  *
278  * \param unique_check  Return true if name is not unique
279  * \param arg  Additional arg to unique_check--meaning is up to caller
280  * \param defname  To initialize name if latter is empty
281  * \param delim  Delimits numeric suffix in name
282  * \param name  Name to be ensured unique
283  * \param name_len  Maximum length of name area
284  * \return true if there if the name was changed
285  */
286 bool BLI_uniquename_cb(
287         UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
288 {
289         if (name[0] == '\0') {
290                 BLI_strncpy(name, defname, name_len);
291         }
292
293         if (unique_check(arg, name)) {
294                 char numstr[16];
295                 char *tempname = alloca(name_len);
296                 char *left = alloca(name_len);
297                 int number;
298                 size_t len = BLI_split_name_num(left, &number, name, delim);
299                 do {
300                         /* add 1 to account for \0 */
301                         const size_t numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number) + 1;
302
303                         /* highly unlikely the string only has enough room for the number
304                          * but support anyway */
305                         if ((len == 0) || (numlen >= name_len)) {
306                                 /* number is know not to be utf-8 */
307                                 BLI_strncpy(tempname, numstr, name_len);
308                         }
309                         else {
310                                 char *tempname_buf;
311                                 tempname_buf = tempname + BLI_strncpy_utf8_rlen(tempname, left, name_len - numlen);
312                                 memcpy(tempname_buf, numstr, numlen);
313                         }
314                 } while (unique_check(arg, tempname));
315
316                 BLI_strncpy(name, tempname, name_len);
317
318                 return true;
319         }
320
321         return false;
322 }
323
324 /* little helper macro for BLI_uniquename */
325 #ifndef GIVE_STRADDR
326 #  define GIVE_STRADDR(data, offset) ( ((char *)data) + offset)
327 #endif
328
329 /* Generic function to set a unique name. It is only designed to be used in situations
330  * where the name is part of the struct.
331  *
332  * For places where this is used, see constraint.c for example...
333  *
334  *  name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
335  *  len: maximum length of string (to prevent overflows, etc.)
336  *  defname: the name that should be used by default if none is specified already
337  *  delim: the character which acts as a delimiter between parts of the name
338  */
339 static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, int name_offs)
340 {
341         Link *link;
342
343         for (link = list->first; link; link = link->next) {
344                 if (link != vlink) {
345                         if (STREQ(GIVE_STRADDR(link, name_offs), name)) {
346                                 return true;
347                         }
348                 }
349         }
350
351         return false;
352 }
353
354 static bool uniquename_unique_check(void *arg, const char *name)
355 {
356         struct {ListBase *lb; void *vlink; int name_offs; } *data = arg;
357         return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
358 }
359
360 /**
361  * Ensures that the specified block has a unique name within the containing list,
362  * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted.
363  *
364  * \param list  List containing the block
365  * \param vlink  The block to check the name for
366  * \param defname  To initialize block name if latter is empty
367  * \param delim  Delimits numeric suffix in name
368  * \param name_offs  Offset of name within block structure
369  * \param name_len  Maximum length of name area
370  */
371 bool BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, int name_offs, size_t name_len)
372 {
373         struct {ListBase *lb; void *vlink; int name_offs; } data;
374         data.lb = list;
375         data.vlink = vlink;
376         data.name_offs = name_offs;
377
378         BLI_assert(name_len > 1);
379
380         /* See if we are given an empty string */
381         if (ELEM(NULL, vlink, defname))
382                 return false;
383
384         return BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
385 }
386
387 /* ------------------------------------------------------------------------- */
388 /** \name Join Strings
389  *
390  * For non array versions of these functions, use the macros:
391  * - #BLI_string_joinN
392  * - #BLI_string_join_by_sep_charN
393  * - #BLI_string_join_by_sep_char_with_tableN
394  *
395  * \{ */
396
397 /**
398  * Join an array of strings into a newly allocated, null terminated string.
399  */
400 char *BLI_string_join_arrayN(
401         const char *strings[], uint strings_len)
402 {
403         uint total_len = 1;
404         for (uint i = 0; i < strings_len; i++) {
405                 total_len += strlen(strings[i]);
406         }
407         char *result = MEM_mallocN(sizeof(char) * total_len, __func__); 
408         char *c = result;
409         for (uint i = 0; i < strings_len; i++) {
410                 c += BLI_strcpy_rlen(c, strings[i]);
411         }
412         return result;
413 }
414
415 /**
416  * A version of #BLI_string_joinN that takes a separator which can be any character including '\0'.
417  */
418 char *BLI_string_join_array_by_sep_charN(
419         char sep, const char *strings[], uint strings_len)
420 {
421         uint total_len = 0;
422         for (uint i = 0; i < strings_len; i++) {
423                 total_len += strlen(strings[i]) + 1;
424         }
425         if (total_len == 0) {
426                 total_len = 1;
427         }
428
429         char *result = MEM_mallocN(sizeof(char) * total_len, __func__); 
430         char *c = result;
431         if (strings_len != 0) {
432                 for (uint i = 0; i < strings_len; i++) {
433                         c += BLI_strcpy_rlen(c, strings[i]);
434                         *c = sep;
435                         c++;
436                 }
437                 c--;
438         }
439         *c = '\0';
440         return result;
441 }
442
443 /**
444  * A version of #BLI_string_join_array_by_sep_charN that takes a table array.
445  * The new location of each string is written into this array.
446  */
447 char *BLI_string_join_array_by_sep_char_with_tableN(
448         char sep, char *table[], const char *strings[], uint strings_len)
449 {
450         uint total_len = 0;
451         for (uint i = 0; i < strings_len; i++) {
452                 total_len += strlen(strings[i]) + 1;
453         }
454         if (total_len == 0) {
455                 total_len = 1;
456         }
457
458         char *result = MEM_mallocN(sizeof(char) * total_len, __func__); 
459         char *c = result;
460         if (strings_len != 0) {
461                 for (uint i = 0; i < strings_len; i++) {
462                         table[i] = c;  /* <-- only difference to BLI_string_join_array_by_sep_charN. */
463                         c += BLI_strcpy_rlen(c, strings[i]);
464                         *c = sep;
465                         c++;
466                 }
467                 c--;
468         }
469         *c = '\0';
470         return result;
471 }
472
473 /** \} */