| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							| 
									
										
										
										
											2008-01-07 19:13:47 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							| 
									
										
										
										
											2009-12-13 15:48:57 +00:00
										 |  |  |  * various string, file, list operations. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bli | 
					
						
							| 
									
										
										
										
											2011-02-27 20:37:56 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-21 17:37:38 +00:00
										 |  |  | #include "DNA_listBase.h"
 | 
					
						
							| 
									
										
										
										
											2008-02-13 13:55:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-13 17:46:30 +00:00
										 |  |  | #include "BLI_fileops.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_fnmatch.h"
 | 
					
						
							| 
									
										
										
										
											2009-12-13 17:46:30 +00:00
										 |  |  | #include "BLI_path_util.h"
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  | #include "BLI_string_utf8.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												T39690: Modifications to Blender's 'temp dir' system.
Current temporary data of Blender suffers one major issue - default 'temp' dir on Windows is never
automatically cleaned up, and can end being quite big when used by Blender, especially when we have
to store per-process data (using getpid() in file names).
To address this, this patch:
* Divides tempdir paths in two, one for 'base' temp dir (the same as previous unique tempdir path),
  the other is a mkdtemp-generated sub-dir, specific to each Blender instance.
* Only uses base tempdir when we need some shallow persistance accross Blender sessions - and we always
  reuse the same filename (quit.blend...) or generate small file (crash reports...).
* Uses temp sub-dir for heavy files like pointcache or renderEXRs (Save Buffer option).
* Erases temp sub-dir on quit or crash.
To get this working it also adds a working 'recursive delete' to BLI_delete() under Windows.
Note that, as in current code, the 'recover render result' hack-feature that was possible
with SaveBuffer option is still removed. A real renderresult cache feature will be added
soon, though.
Reviewers: campbellbarton, brecht, sergey
Reviewed By: campbellbarton, sergey
CC: sergey
Differential Revision: https://developer.blender.org/D531
											
										 
											2014-06-23 13:42:19 +02:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2013-03-29 00:50:52 +00:00
										 |  |  | #  include "utf_winfunc.h"
 | 
					
						
							|  |  |  | #  include "utfconv.h"
 | 
					
						
							| 
									
										
										
										
											2011-11-02 22:00:22 +00:00
										 |  |  | #  include <io.h>
 | 
					
						
							|  |  |  | #  ifdef _WIN32_IE
 | 
					
						
							|  |  |  | #    undef _WIN32_IE
 | 
					
						
							|  |  |  | #  endif
 | 
					
						
							|  |  |  | #  define _WIN32_IE 0x0501
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  | #  include "BLI_alloca.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #  include "BLI_winstuff.h"
 | 
					
						
							|  |  |  | #  include <shlobj.h>
 | 
					
						
							|  |  |  | #  include <windows.h>
 | 
					
						
							| 
									
										
										
										
											2015-04-08 21:57:49 +02:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #  include "unistd.h"
 | 
					
						
							| 
									
										
										
										
											2010-03-20 18:52:03 +00:00
										 |  |  | #endif /* WIN32 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Declarations */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-25 01:14:39 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Return true if the path is absolute ie starts with a drive specifier | 
					
						
							|  |  |  |  * (eg A:\) or is a UNC path. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  | static bool BLI_path_is_abs(const char *name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* WIN32 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | // #define DEBUG_STRSIZE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | /* implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Looks for a sequence of decimal digits in string, preceding any filename extension, | 
					
						
							|  |  |  |  * returning the integer value if found, or 0 if not. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-12 12:17:42 +11:00
										 |  |  |  * \param string: String to scan. | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  * \param head: Optional area to return copy of part of string prior to digits, | 
					
						
							|  |  |  |  * or before dot if no digits. | 
					
						
							|  |  |  |  * \param tail: Optional area to return copy of part of string following digits, | 
					
						
							|  |  |  |  * or from dot if no digits. | 
					
						
							| 
									
										
										
										
											2018-12-12 12:17:42 +11:00
										 |  |  |  * \param r_num_len: Optional to return number of digits found. | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_num_len) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-28 17:48:45 +11:00
										 |  |  |   uint nums = 0, nume = 0; | 
					
						
							| 
									
										
										
										
											2013-11-24 16:20:04 +11:00
										 |  |  |   int i; | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |   bool found_digit = false; | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   const char *const lslash = BLI_path_slash_rfind(string); | 
					
						
							| 
									
										
										
										
											2017-10-28 17:48:45 +11:00
										 |  |  |   const uint string_len = strlen(string); | 
					
						
							|  |  |  |   const uint lslash_len = lslash != NULL ? (int)(lslash - string) : 0; | 
					
						
							|  |  |  |   uint name_end = string_len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |   while (name_end > lslash_len && string[--name_end] != '.') { | 
					
						
							|  |  |  |     /* name ends at dot if present */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (name_end == lslash_len && string[name_end] != '.') { | 
					
						
							|  |  |  |     name_end = string_len; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-25 21:13:58 +11:00
										 |  |  |   for (i = name_end - 1; i >= (int)lslash_len; i--) { | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     if (isdigit(string[i])) { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |       if (found_digit) { | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |         nums = i; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |       else { | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |         nume = i; | 
					
						
							|  |  |  |         nums = i; | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |         found_digit = true; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-10-04 10:50:15 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |       if (found_digit) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |   if (found_digit) { | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |     const long long int ret = strtoll(&(string[nums]), NULL, 10); | 
					
						
							| 
									
										
										
										
											2018-06-01 11:58:50 +02:00
										 |  |  |     if (ret >= INT_MIN && ret <= INT_MAX) { | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |       if (tail) { | 
					
						
							|  |  |  |         strcpy(tail, &string[nume + 1]); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-06-01 11:58:50 +02:00
										 |  |  |       if (head) { | 
					
						
							|  |  |  |         strcpy(head, string); | 
					
						
							|  |  |  |         head[nums] = 0; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |       if (r_num_len) { | 
					
						
							|  |  |  |         *r_num_len = nume - nums + 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return (int)ret; | 
					
						
							| 
									
										
										
										
											2010-07-04 17:14:06 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |   if (tail) { | 
					
						
							|  |  |  |     strcpy(tail, string + name_end); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-01 11:58:50 +02:00
										 |  |  |   if (head) { | 
					
						
							|  |  |  |     /* name_end points to last character of head,
 | 
					
						
							|  |  |  |      * make it +1 so null-terminator is nicely placed | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     BLI_strncpy(head, string, name_end + 1); | 
					
						
							| 
									
										
										
										
											2010-07-04 17:14:06 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-11 10:43:34 +02:00
										 |  |  |   if (r_num_len) { | 
					
						
							|  |  |  |     *r_num_len = 0; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-01 11:58:50 +02:00
										 |  |  |   return 0; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic | 
					
						
							|  |  |  |  * is formatted as numlen digits with leading zeroes. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_sequence_encode( | 
					
						
							| 
									
										
										
										
											2010-04-23 23:01:50 +00:00
										 |  |  |     char *string, const char *head, const char *tail, unsigned short numlen, int pic) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-10 11:02:21 +00:00
										 |  |  |   sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */ | 
					
						
							| 
									
										
										
										
											2010-11-07 08:49:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  | /* ******************** string encoding ***************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-17 16:04:54 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Remove redundant characters from \a path and optionally make absolute. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2016-06-27 13:20:56 +10:00
										 |  |  |  * \param relabase: The path this is relative to, or ignored when NULL. | 
					
						
							| 
									
										
										
										
											2015-10-17 16:04:54 +11:00
										 |  |  |  * \param path: Can be any input, and this function converts it to a regular full path. | 
					
						
							|  |  |  |  * Also removes garbage from directory paths, like `/../` or double slashes etc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note \a path isn't protected for max string names... | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_normalize(const char *relabase, char *path) | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-12-21 20:56:49 +00:00
										 |  |  |   ptrdiff_t a; | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   char *start, *eind; | 
					
						
							| 
									
										
										
										
											2008-04-28 21:29:15 +00:00
										 |  |  |   if (relabase) { | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |     BLI_path_abs(path, relabase); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |     if (path[0] == '/' && path[1] == '/') { | 
					
						
							|  |  |  |       if (path[2] == '\0') { | 
					
						
							| 
									
										
										
										
											2021-06-22 10:42:32 -07:00
										 |  |  |         return; /* path is "//" - can't clean it */ | 
					
						
							| 
									
										
										
										
											2008-06-05 13:02:00 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |       path = path + 2; /* leave the initial "//" untouched */ | 
					
						
							| 
									
										
										
										
											2008-06-05 13:02:00 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-04-28 21:29:15 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-11 09:04:41 +00:00
										 |  |  |   /* Note
 | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |    *   memmove(start, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2008-06-11 09:04:41 +00:00
										 |  |  |    * is the same as | 
					
						
							| 
									
										
										
										
											2015-02-07 04:33:48 +11:00
										 |  |  |    *   strcpy(start, eind); | 
					
						
							| 
									
										
										
										
											2008-06-11 09:04:41 +00:00
										 |  |  |    * except strcpy should not be used because there is overlap, | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |    * so use memmove's slightly more obscure syntax - Campbell | 
					
						
							| 
									
										
										
										
											2008-06-11 09:04:41 +00:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |   while ((start = strstr(path, "\\..\\"))) { | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |     eind = start + strlen("\\..\\") - 1; | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |     a = start - path - 1; | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     while (a > 0) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |       if (path[a] == '\\') { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |       a--; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     if (a < 0) { | 
					
						
							| 
									
										
										
										
											2008-06-14 16:54:46 +00:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |       memmove(path + a, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2008-06-14 16:54:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |   while ((start = strstr(path, "\\.\\"))) { | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |     eind = start + strlen("\\.\\") - 1; | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |     memmove(start, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   /* remove two consecutive backslashes, but skip the UNC prefix,
 | 
					
						
							|  |  |  |    * which needs to be preserved */ | 
					
						
							|  |  |  |   while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) { | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |     eind = start + strlen("\\\\") - 1; | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |     memmove(start, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2007-12-31 12:03:26 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |   while ((start = strstr(path, "/../"))) { | 
					
						
							|  |  |  |     a = start - path - 1; | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |     if (a > 0) { | 
					
						
							|  |  |  |       /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */ | 
					
						
							|  |  |  |       eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */ | 
					
						
							|  |  |  |       while (a > 0 && path[a] != '/') {                /* find start of <parent> */ | 
					
						
							|  |  |  |         a--; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       memmove(path + a, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |       /* support for odd paths: eg /../home/me --> /home/me
 | 
					
						
							| 
									
										
										
										
											2021-06-22 10:42:32 -07:00
										 |  |  |        * this is a valid path in blender but we can't handle this the usual way below | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |        * simply strip this prefix then evaluate the path as usual. | 
					
						
							|  |  |  |        * pythons os.path.normpath() does this */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |       /* Note: previous version of following call used an offset of 3 instead of 4,
 | 
					
						
							|  |  |  |        * which meant that the "/../home/me" example actually became "home/me". | 
					
						
							| 
									
										
										
										
											2020-07-10 16:04:09 +10:00
										 |  |  |        * Using offset of 3 gives behavior consistent with the aforementioned | 
					
						
							| 
									
										
										
										
											2013-03-10 04:43:15 +00:00
										 |  |  |        * Python routine. */ | 
					
						
							|  |  |  |       memmove(path, path + 3, strlen(path + 3) + 1); | 
					
						
							| 
									
										
										
										
											2008-06-14 16:54:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |   while ((start = strstr(path, "/./"))) { | 
					
						
							| 
									
										
										
										
											2010-09-17 15:11:12 +00:00
										 |  |  |     eind = start + (3 - 1) /* strlen("/./") - 1 */; | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |     memmove(start, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 04:35:14 +00:00
										 |  |  |   while ((start = strstr(path, "//"))) { | 
					
						
							| 
									
										
										
										
											2010-09-17 15:11:12 +00:00
										 |  |  |     eind = start + (2 - 1) /* strlen("//") - 1 */; | 
					
						
							| 
									
										
										
										
											2012-03-11 19:09:01 +00:00
										 |  |  |     memmove(start, eind, strlen(eind) + 1); | 
					
						
							| 
									
										
										
										
											2005-12-14 13:21:32 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-17 16:04:54 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Cleanup filepath ensuring a trailing slash. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_normalize_dir(const char *relabase, char *dir) | 
					
						
							| 
									
										
										
										
											2011-03-11 00:30:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-08 12:37:46 +01:00
										 |  |  |   /* Would just create an unexpected "/" path, just early exit entirely. */ | 
					
						
							|  |  |  |   if (dir[0] == '\0') { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   BLI_path_normalize(relabase, dir); | 
					
						
							|  |  |  |   BLI_path_slash_ensure(dir); | 
					
						
							| 
									
										
										
										
											2011-03-11 00:30:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Make given name safe to be used in paths. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |  * \return true if \a fname was changed, false otherwise. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  |  * For now, simply replaces reserved chars (as listed in | 
					
						
							| 
									
										
										
										
											2016-10-25 17:32:58 +02:00
										 |  |  |  * https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
 | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  |  * by underscores ('_'). | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  * \note Space case ' ' is a bit of an edge case here - in theory it is allowed, | 
					
						
							|  |  |  |  * but again can be an issue in some cases, so we simply replace it by an underscore too | 
					
						
							|  |  |  |  * (good practice anyway). | 
					
						
							|  |  |  |  * REMOVED based on popular demand (see T45900). | 
					
						
							|  |  |  |  * Percent '%' char is a bit same case - not recommended to use it, | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * but supported by all decent file-systems/operating-systems around. | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  * \note On Windows, it also ensures there is no '.' (dot char) at the end of the file, | 
					
						
							|  |  |  |  * this can lead to issues. | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note On Windows, it also checks for forbidden names | 
					
						
							| 
									
										
										
										
											2019-04-22 00:54:27 +10:00
										 |  |  |  * (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx ).
 | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  | bool BLI_filename_make_safe(char *fname) | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-15 07:44:25 +02:00
										 |  |  |   const char *invalid = | 
					
						
							|  |  |  |       "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |       "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" | 
					
						
							| 
									
										
										
										
											2015-10-18 18:51:08 +02:00
										 |  |  |       "/\\?*:|\"<>"; | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   char *fn; | 
					
						
							|  |  |  |   bool changed = false; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   if (*fname == '\0') { | 
					
						
							|  |  |  |     return changed; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   for (fn = fname; *fn && (fn = strpbrk(fn, invalid)); fn++) { | 
					
						
							|  |  |  |     *fn = '_'; | 
					
						
							|  |  |  |     changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   /* Forbid only dots. */ | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   for (fn = fname; *fn == '.'; fn++) { | 
					
						
							|  |  |  |     /* pass */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   if (*fn == '\0') { | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  |     *fname = '_'; | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |     changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const size_t len = strlen(fname); | 
					
						
							|  |  |  |     const char *invalid_names[] = { | 
					
						
							|  |  |  |         "con",  "prn",  "aux",  "null", "com1", "com2", "com3", "com4", | 
					
						
							|  |  |  |         "com5", "com6", "com7", "com8", "com9", "lpt1", "lpt2", "lpt3", | 
					
						
							|  |  |  |         "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", NULL, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     char *lower_fname = BLI_strdup(fname); | 
					
						
							|  |  |  |     const char **iname; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |     /* Forbid trailing dot (trailing space has already been replaced above). */ | 
					
						
							|  |  |  |     if (fname[len - 1] == '.') { | 
					
						
							|  |  |  |       fname[len - 1] = '_'; | 
					
						
							|  |  |  |       changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |     /* Check for forbidden names - not we have to check all combination
 | 
					
						
							|  |  |  |      * of upper and lower cases, hence the usage of lower_fname | 
					
						
							|  |  |  |      * (more efficient than using BLI_strcasestr repeatedly). */ | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |     BLI_str_tolower_ascii(lower_fname, len); | 
					
						
							|  |  |  |     for (iname = invalid_names; *iname; iname++) { | 
					
						
							|  |  |  |       if (strstr(lower_fname, *iname) == lower_fname) { | 
					
						
							|  |  |  |         const size_t iname_len = strlen(*iname); | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |         /* Only invalid if the whole name is made of the invalid chunk, or it has an
 | 
					
						
							|  |  |  |          * (assumed extension) dot just after. This means it will also catch 'valid' | 
					
						
							|  |  |  |          * names like 'aux.foo.bar', but should be | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |          * good enough for us! */ | 
					
						
							|  |  |  |         if ((iname_len == len) || (lower_fname[iname_len] == '.')) { | 
					
						
							|  |  |  |           *fname = '_'; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |     MEM_freeN(lower_fname); | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return changed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Make given path OS-safe. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \return true if \a path was changed, false otherwise. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_make_safe(char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Simply apply BLI_filename_make_safe() over each component of the path.
 | 
					
						
							| 
									
										
										
										
											2015-10-07 15:02:06 +11:00
										 |  |  |    * Luckily enough, same 'safe' rules applies to filenames and dirnames. */ | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   char *curr_slash, *curr_path = path; | 
					
						
							|  |  |  |   bool changed = false; | 
					
						
							|  |  |  |   bool skip_first = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |   if (BLI_path_is_abs(path)) { | 
					
						
							|  |  |  |     /* Do not make safe 'C:' in 'C:\foo\bar'... */ | 
					
						
							|  |  |  |     skip_first = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   for (curr_slash = (char *)BLI_path_slash_find(curr_path); curr_slash; | 
					
						
							|  |  |  |        curr_slash = (char *)BLI_path_slash_find(curr_path)) { | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |     const char backup = *curr_slash; | 
					
						
							|  |  |  |     *curr_slash = '\0'; | 
					
						
							|  |  |  |     if (!skip_first && (*curr_path != '\0') && BLI_filename_make_safe(curr_path)) { | 
					
						
							|  |  |  |       changed = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     skip_first = false; | 
					
						
							|  |  |  |     curr_path = curr_slash + 1; | 
					
						
							|  |  |  |     *curr_slash = backup; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (BLI_filename_make_safe(curr_path)) { | 
					
						
							|  |  |  |     changed = true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-14 18:42:22 +02:00
										 |  |  |   return changed; | 
					
						
							| 
									
										
										
										
											2015-01-16 18:48:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Does path begin with the special "//" prefix that Blender uses to indicate | 
					
						
							|  |  |  |  * a path relative to the .blend file. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_is_rel(const char *path) | 
					
						
							| 
									
										
										
										
											2012-08-29 10:32:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   return path[0] == '/' && path[1] == '/'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | /* return true if the path is a UNC share */ | 
					
						
							|  |  |  | bool BLI_path_is_unc(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return name[0] == '\\' && name[1] == '\\'; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Returns the length of the identifying prefix | 
					
						
							|  |  |  |  * of a UNC path which can start with '\\' (short version) | 
					
						
							|  |  |  |  * or '\\?\' (long version) | 
					
						
							|  |  |  |  * If the path is not a UNC path, return 0 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int BLI_path_unc_prefix_len(const char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (BLI_path_is_unc(path)) { | 
					
						
							|  |  |  |     if ((path[2] == '?') && (path[3] == '\\')) { | 
					
						
							|  |  |  |       /* we assume long UNC path like \\?\server\share\folder etc... */ | 
					
						
							|  |  |  |       return 4; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return 2; | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(WIN32)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-25 01:14:39 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Return true if the path is absolute ie starts with a drive specifier | 
					
						
							|  |  |  |  * (eg A:\) or is a UNC path. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | static bool BLI_path_is_abs(const char *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |   return (name[1] == ':' && ELEM(name[2], '\\', '/')) || BLI_path_is_unc(name); | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static wchar_t *next_slash(wchar_t *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   wchar_t *slash = path; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   while (*slash && *slash != L'\\') { | 
					
						
							|  |  |  |     slash++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   return slash; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 16:23:34 +11:00
										 |  |  | /* Adds a slash if the UNC path points to a share. */ | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | static void BLI_path_add_slash_to_share(wchar_t *uncpath) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   wchar_t *slash_after_server = next_slash(uncpath + 2); | 
					
						
							|  |  |  |   if (*slash_after_server) { | 
					
						
							|  |  |  |     wchar_t *slash_after_share = next_slash(slash_after_server + 1); | 
					
						
							|  |  |  |     if (!(*slash_after_share)) { | 
					
						
							|  |  |  |       slash_after_share[0] = L'\\'; | 
					
						
							|  |  |  |       slash_after_share[1] = L'\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void BLI_path_unc_to_short(wchar_t *unc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   wchar_t tmp[PATH_MAX]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   int len = wcslen(unc); | 
					
						
							|  |  |  |   /* convert:
 | 
					
						
							|  |  |  |    *    \\?\UNC\server\share\folder\... to \\server\share\folder\... | 
					
						
							|  |  |  |    *    \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\... | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   if ((len > 3) && (unc[0] == L'\\') && (unc[1] == L'\\') && (unc[2] == L'?') && | 
					
						
							| 
									
										
										
										
											2020-03-06 12:49:15 -03:00
										 |  |  |       ELEM(unc[3], L'\\', L'/')) { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     if ((len > 5) && (unc[5] == L':')) { | 
					
						
							|  |  |  |       wcsncpy(tmp, unc + 4, len - 4); | 
					
						
							|  |  |  |       tmp[len - 4] = L'\0'; | 
					
						
							|  |  |  |       wcscpy(unc, tmp); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |     else if ((len > 7) && (wcsncmp(&unc[4], L"UNC", 3) == 0) && ELEM(unc[7], L'\\', L'/')) { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |       tmp[0] = L'\\'; | 
					
						
							|  |  |  |       tmp[1] = L'\\'; | 
					
						
							|  |  |  |       wcsncpy(tmp + 2, unc + 8, len - 8); | 
					
						
							|  |  |  |       tmp[len - 6] = L'\0'; | 
					
						
							|  |  |  |       wcscpy(unc, tmp); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_normalize_unc(char *path, int maxlen) | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   wchar_t *tmp_16 = alloc_utf16_from_8(path, 1); | 
					
						
							| 
									
										
										
										
											2020-04-08 16:29:46 +10:00
										 |  |  |   BLI_path_normalize_unc_16(tmp_16); | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   conv_utf_16_to_8(tmp_16, path, maxlen); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-08 16:29:46 +10:00
										 |  |  | void BLI_path_normalize_unc_16(wchar_t *path_16) | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   BLI_path_unc_to_short(path_16); | 
					
						
							|  |  |  |   BLI_path_add_slash_to_share(path_16); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Replaces `file` with a relative version (prefixed by "//") such that #BLI_path_abs, given | 
					
						
							|  |  |  |  * the same `relfile`, will convert it back to its original value. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-03-09 17:36:23 +00:00
										 |  |  | void BLI_path_rel(char *file, const char *relfile) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |   const char *lslash; | 
					
						
							| 
									
										
										
										
											2011-11-26 04:07:38 +00:00
										 |  |  |   char temp[FILE_MAX]; | 
					
						
							|  |  |  |   char res[FILE_MAX]; | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-12-11 22:03:04 +00:00
										 |  |  |   /* if file is already relative, bail out */ | 
					
						
							| 
									
										
										
										
											2012-08-29 10:32:38 +00:00
										 |  |  |   if (BLI_path_is_rel(file)) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |   /* also bail out if relative path is not set */ | 
					
						
							| 
									
										
										
										
											2012-08-29 10:32:38 +00:00
										 |  |  |   if (relfile[0] == '\0') { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 23:50:55 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     char *ptemp; | 
					
						
							| 
									
										
										
										
											2007-02-21 20:00:03 +00:00
										 |  |  |     /* fix missing volume name in relative base,
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |      * can happen with old recent-files.txt files */ | 
					
						
							| 
									
										
										
										
											2020-08-26 15:50:48 +02:00
										 |  |  |     BLI_windows_get_default_root_dir(temp); | 
					
						
							| 
									
										
										
										
											2007-02-21 20:00:03 +00:00
										 |  |  |     ptemp = &temp[2]; | 
					
						
							|  |  |  |     if (relfile[0] != '\\' && relfile[0] != '/') { | 
					
						
							|  |  |  |       ptemp++; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     BLI_strncpy(ptemp, relfile, FILE_MAX - 3); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2011-11-26 04:07:38 +00:00
										 |  |  |     BLI_strncpy(temp, relfile, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2007-02-21 20:00:03 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-12-05 23:50:55 +00:00
										 |  |  |   if (BLI_strnlen(file, 3) > 2) { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     bool is_unc = BLI_path_is_unc(file); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     /* Ensure paths are both UNC paths or are both drives */ | 
					
						
							|  |  |  |     if (BLI_path_is_unc(temp) != is_unc) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     /* Ensure both UNC paths are on the same share */ | 
					
						
							|  |  |  |     if (is_unc) { | 
					
						
							|  |  |  |       int off; | 
					
						
							|  |  |  |       int slash = 0; | 
					
						
							|  |  |  |       for (off = 0; temp[off] && slash < 4; off++) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |         if (temp[off] != file[off]) { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |           return; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |         if (temp[off] == '\\') { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |           slash++; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-18 20:47:43 +11:00
										 |  |  |     else if ((temp[1] == ':' && file[1] == ':') && (tolower(temp[0]) != tolower(file[0]))) { | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2007-02-21 20:00:03 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   BLI_strncpy(temp, relfile, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2005-05-20 12:18:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-30 15:18:03 +10:00
										 |  |  |   BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/'); | 
					
						
							|  |  |  |   BLI_str_replace_char(file + BLI_path_unc_prefix_len(file), '\\', '/'); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-28 21:29:15 +00:00
										 |  |  |   /* remove /./ which confuse the following slash counting... */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   BLI_path_normalize(NULL, file); | 
					
						
							|  |  |  |   BLI_path_normalize(NULL, temp); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |   /* the last slash in the file indicates where the path part ends */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   lslash = BLI_path_slash_rfind(temp); | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-06 18:40:15 +00:00
										 |  |  |   if (lslash) { | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |     /* find the prefix of the filename that is equal for both filenames.
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |      * This is replaced by the two slashes at the beginning */ | 
					
						
							| 
									
										
										
										
											2014-04-27 00:20:55 +10:00
										 |  |  |     const char *p = temp; | 
					
						
							|  |  |  |     const char *q = file; | 
					
						
							| 
									
										
										
										
											2013-06-27 20:47:59 +00:00
										 |  |  |     char *r = res; | 
					
						
							| 
									
										
										
										
											2010-06-03 13:05:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-08 06:47:41 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |     while (tolower(*p) == tolower(*q)) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     while (*p == *q) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-05-09 09:24:15 +00:00
										 |  |  |       p++; | 
					
						
							|  |  |  |       q++; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |       /* don't search beyond the end of the string
 | 
					
						
							| 
									
										
										
										
											2010-06-03 13:05:45 +00:00
										 |  |  |        * in the rare case they match */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       if ((*p == '\0') || (*q == '\0')) { | 
					
						
							| 
									
										
										
										
											2010-06-03 13:05:45 +00:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2010-06-03 13:05:45 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  |     /* we might have passed the slash when the beginning of a dir matches
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |      * so we rewind. Only check on the actual filename | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |     if (*q != '/') { | 
					
						
							|  |  |  |       while ((q >= file) && (*q != '/')) { | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |         q--; | 
					
						
							|  |  |  |         p--; | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |     else if (*p != '/') { | 
					
						
							|  |  |  |       while ((p >= temp) && (*p != '/')) { | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |         p--; | 
					
						
							|  |  |  |         q--; | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-27 20:47:59 +00:00
										 |  |  |     r += BLI_strcpy_rlen(r, "//"); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  |     /* p now points to the slash that is at the beginning of the part
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  |      * where the path is different from the relative path. | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |      * We count the number of directories we need to go up in the | 
					
						
							|  |  |  |      * hierarchy to arrive at the common 'prefix' of the path | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     if (p < temp) { | 
					
						
							|  |  |  |       p = temp; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     while (p && p < lslash) { | 
					
						
							| 
									
										
										
										
											2013-06-27 20:47:59 +00:00
										 |  |  |       if (*p == '/') { | 
					
						
							|  |  |  |         r += BLI_strcpy_rlen(r, "../"); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-05-09 09:24:15 +00:00
										 |  |  |       p++; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-27 20:47:59 +00:00
										 |  |  |     /* don't copy the slash at the beginning */ | 
					
						
							| 
									
										
										
										
											2020-10-26 16:31:11 +01:00
										 |  |  |     r += BLI_strncpy_rlen(r, q + 1, FILE_MAX - (r - res)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2015-06-30 15:18:03 +10:00
										 |  |  |     BLI_str_replace_char(res + 2, '/', '\\'); | 
					
						
							| 
									
										
										
										
											2005-10-24 20:52:51 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     strcpy(file, res); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Appends a suffix to the string, fitting it before the extension | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * string = Foo.png, suffix = 123, separator = _ | 
					
						
							|  |  |  |  * Foo.png -> Foo_123.png | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-12 12:50:58 +11:00
										 |  |  |  * \param string: original (and final) string | 
					
						
							|  |  |  |  * \param maxlen: Maximum length of string | 
					
						
							|  |  |  |  * \param suffix: String to append to the original string | 
					
						
							|  |  |  |  * \param sep: Optional separator character | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * \return true if succeeded | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char *sep) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(string, 0xff, sizeof(*string) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |   const size_t string_len = strlen(string); | 
					
						
							|  |  |  |   const size_t suffix_len = strlen(suffix); | 
					
						
							|  |  |  |   const size_t sep_len = strlen(sep); | 
					
						
							|  |  |  |   ssize_t a; | 
					
						
							|  |  |  |   char extension[FILE_MAX]; | 
					
						
							|  |  |  |   bool has_extension = false; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (string_len + sep_len + suffix_len >= maxlen) { | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |   for (a = string_len - 1; a >= 0; a--) { | 
					
						
							|  |  |  |     if (string[a] == '.') { | 
					
						
							|  |  |  |       has_extension = true; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |     if (ELEM(string[a], '/', '\\')) { | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (!has_extension) { | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |     a = string_len; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-16 14:25:23 -03:00
										 |  |  |   BLI_strncpy(extension, string + a, sizeof(extension)); | 
					
						
							|  |  |  |   sprintf(string + a, "%s%s%s", sep, suffix, extension); | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * Replaces path with the path of its parent directory, returning true if | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * it was able to find a parent directory within the path. | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | bool BLI_path_parent_dir(char *path) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-01-31 03:28:53 +11:00
										 |  |  |   const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   char tmp[FILE_MAX + 4]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-19 10:39:49 +00:00
										 |  |  |   BLI_join_dirfile(tmp, sizeof(tmp), path, parent_dir); | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  |   if (!BLI_path_extension_check(tmp, parent_dir)) { | 
					
						
							| 
									
										
										
										
											2015-04-08 21:57:49 +02:00
										 |  |  |     strcpy(path, tmp); /* We assume pardir is always shorter... */ | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2008-09-22 15:37:32 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-15 10:33:16 +11:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Strips off nonexistent (or non-accessible) sub-directories from the end of `dir`, | 
					
						
							| 
									
										
										
										
											2020-02-15 10:33:16 +11:00
										 |  |  |  * leaving the path of the lowest-level directory that does exist and we can read. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | bool BLI_path_parent_dir_until_exists(char *dir) | 
					
						
							| 
									
										
										
										
											2020-02-15 10:33:16 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   bool valid_path = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Loop as long as cur path is not a dir, and we can get a parent path. */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_path_parent_dir(dir))) { | 
					
						
							| 
									
										
										
										
											2020-02-15 10:33:16 +11:00
										 |  |  |     /* pass */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return (valid_path && dir[0]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Looks for a sequence of "#" characters in the last slash-separated component of `path`, | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  * returning the indexes of the first and one past the last character in the sequence in | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * `char_start` and `char_end` respectively. Returns true if such a sequence was found. | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | static bool stringframe_chars(const char *path, int *char_start, int *char_end) | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-10-28 17:48:45 +11:00
										 |  |  |   uint ch_sta, ch_end, i; | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  |   /* Insert current frame: file### -> file001 */ | 
					
						
							|  |  |  |   ch_sta = ch_end = 0; | 
					
						
							|  |  |  |   for (i = 0; path[i] != '\0'; i++) { | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |     if (ELEM(path[i], '\\', '/')) { | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |       ch_end = 0; /* this is a directory name, don't use any hashes we found */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (path[i] == '#') { | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  |       ch_sta = i; | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       ch_end = ch_sta + 1; | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  |       while (path[ch_end] == '#') { | 
					
						
							|  |  |  |         ch_end++; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       i = ch_end - 1; /* keep searching */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |       /* don't break, there may be a slash after this that invalidates the previous #'s */ | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   if (ch_end) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     *char_start = ch_sta; | 
					
						
							|  |  |  |     *char_end = ch_end; | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   *char_start = -1; | 
					
						
							|  |  |  |   *char_end = -1; | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Ensure `path` contains at least one "#" character in its last slash-separated | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  * component, appending one digits long if not. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  | static void ensure_digits(char *path, int digits) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   char *file = (char *)BLI_path_slash_rfind(path); | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (file == NULL) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     file = path; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   if (strrchr(file, '#') == NULL) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     int len = strlen(file); | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |     while (digits--) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       file[len++] = '#'; | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     file[len] = '\0'; | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Replaces "#" character sequence in last slash-separated component of `path` | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * with frame as decimal integer, with leading zeroes as necessary, to make digits digits. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_frame(char *path, int frame, int digits) | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int ch_sta, ch_end; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (digits) { | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  |     ensure_digits(path, digits); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  |   if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ | 
					
						
							| 
									
										
										
										
											2010-11-01 01:46:26 +00:00
										 |  |  |     char tmp[FILE_MAX]; | 
					
						
							| 
									
										
										
										
											2013-07-23 12:49:30 +00:00
										 |  |  |     BLI_snprintf( | 
					
						
							|  |  |  |         tmp, sizeof(tmp), "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end); | 
					
						
							|  |  |  |     BLI_strncpy(path, tmp, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2008-05-04 09:41:15 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Replaces "#" character sequence in last slash-separated component of `path` | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * with sta and end as decimal integers, with leading zeroes as necessary, to make digits | 
					
						
							|  |  |  |  * digits each, with a hyphen in-between. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_frame_range(char *path, int sta, int end, int digits) | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int ch_sta, ch_end; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (digits) { | 
					
						
							| 
									
										
										
										
											2010-01-30 22:33:47 +00:00
										 |  |  |     ensure_digits(path, digits); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  |   if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ | 
					
						
							| 
									
										
										
										
											2011-03-29 14:07:07 +00:00
										 |  |  |     char tmp[FILE_MAX]; | 
					
						
							| 
									
										
										
										
											2012-01-11 12:33:51 +00:00
										 |  |  |     BLI_snprintf(tmp, | 
					
						
							|  |  |  |                  sizeof(tmp), | 
					
						
							|  |  |  |                  "%.*s%.*d-%.*d%s", | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |                  ch_sta, | 
					
						
							|  |  |  |                  path, | 
					
						
							|  |  |  |                  ch_end - ch_sta, | 
					
						
							|  |  |  |                  sta, | 
					
						
							|  |  |  |                  ch_end - ch_sta, | 
					
						
							|  |  |  |                  end, | 
					
						
							|  |  |  |                  path + ch_end); | 
					
						
							| 
									
										
										
										
											2012-01-11 12:33:51 +00:00
										 |  |  |     BLI_strncpy(path, tmp, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2010-01-26 21:41:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Get the frame from a filename formatted by blender's frame scheme | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-17 16:06:45 +11:00
										 |  |  |   if (*path) { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |     char *file = (char *)BLI_path_slash_rfind(path); | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  |     char *c; | 
					
						
							|  |  |  |     int len, numdigits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     numdigits = *r_numdigits = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     if (file == NULL) { | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  |       file = path; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* first get the extension part */ | 
					
						
							|  |  |  |     len = strlen(file); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c = file + len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* isolate extension */ | 
					
						
							|  |  |  |     while (--c != file) { | 
					
						
							|  |  |  |       if (*c == '.') { | 
					
						
							|  |  |  |         c--; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* find start of number */ | 
					
						
							|  |  |  |     while (c != (file - 1) && isdigit(*c)) { | 
					
						
							|  |  |  |       c--; | 
					
						
							|  |  |  |       numdigits++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (numdigits) { | 
					
						
							|  |  |  |       char prevchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c++; | 
					
						
							|  |  |  |       prevchar = c[numdigits]; | 
					
						
							|  |  |  |       c[numdigits] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* was the number really an extension? */ | 
					
						
							|  |  |  |       *r_frame = atoi(c); | 
					
						
							|  |  |  |       c[numdigits] = prevchar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       *r_numdigits = numdigits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Fix BLI_path_frame_strip
The `BLI_path_frame_strip` function was completely broken, unless the
number of digits in the sequence number was the same as the length of
the extension. In other words, it would work fine for `file.0001.abc` (4
digit `0001` and 4 char `.abc`), but other combinations would truncate
to the shortest (`file.001.abc` would become `file.###.ab` and
`file.00001.a` would become `file.##.a`). The dependency between the
sequence number and the file extension is now removed.
The behaviour has changed a little bit in the case where there are no
numbers in the filename. Previously, `path="filename.abc"` would result
in `path="filename.abc"` and `ext=""`, but now it results in
`path="filename"` and `ext=".abc"`. This way `ext` always contains the
extension, and the behaviour is consistent regardless of whether there
were any numbers found.
Furthermore, I've removed the `bool set_frame_char` parameter, because
it was unclear, probably also buggy, and most importantly, never used.
I've also added a unit test for the `BLI_path_frame_strip` function.
											
										 
											2019-03-20 12:59:11 +01:00
										 |  |  | void BLI_path_frame_strip(char *path, char *r_ext) | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-16 16:49:55 +02:00
										 |  |  |   *r_ext = '\0'; | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   if (*path == '\0') { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   char *file = (char *)BLI_path_slash_rfind(path); | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   char *c, *suffix; | 
					
						
							|  |  |  |   int len; | 
					
						
							|  |  |  |   int numdigits = 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (file == NULL) { | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |     file = path; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   /* first get the extension part */ | 
					
						
							|  |  |  |   len = strlen(file); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   c = file + len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   /* isolate extension */ | 
					
						
							|  |  |  |   while (--c != file) { | 
					
						
							|  |  |  |     if (*c == '.') { | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  |       c--; | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   suffix = c + 1; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   /* find start of number */ | 
					
						
							|  |  |  |   while (c != (file - 1) && isdigit(*c)) { | 
					
						
							|  |  |  |     c--; | 
					
						
							|  |  |  |     numdigits++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   c++; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   int suffix_length = len - (suffix - file); | 
					
						
							| 
									
										
										
										
											2019-03-21 00:58:01 +11:00
										 |  |  |   BLI_strncpy(r_ext, suffix, suffix_length + 1); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   /* replace the number with the suffix and terminate the string */ | 
					
						
							|  |  |  |   while (numdigits--) { | 
					
						
							|  |  |  |     *c++ = '#'; | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-03-20 13:39:27 +01:00
										 |  |  |   *c = '\0'; | 
					
						
							| 
									
										
										
										
											2015-06-04 20:40:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-25 16:59:10 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_frame_check_chars(const char *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int ch_sta, ch_end; /* dummy args */ | 
					
						
							|  |  |  |   return stringframe_chars(path, &ch_sta, &ch_end); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Creates a display string from path to be used menus and the user interface. | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Like `bpy.path.display_name()`. | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Strip leading underscores and spaces. */ | 
					
						
							|  |  |  |   int strip_offset = 0; | 
					
						
							|  |  |  |   while (ELEM(name[strip_offset], '_', ' ')) { | 
					
						
							|  |  |  |     strip_offset++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |   BLI_strncpy(display_name, name + strip_offset, maxlen); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |   /* Replace underscores with spaces. */ | 
					
						
							|  |  |  |   BLI_str_replace_char(display_name, '_', ' '); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |   /* Strip extension. */ | 
					
						
							|  |  |  |   BLI_path_extension_replace(display_name, maxlen, ""); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |   /* Test if string has any upper case characters. */ | 
					
						
							|  |  |  |   bool all_lower = true; | 
					
						
							|  |  |  |   for (int i = 0; display_name[i]; i++) { | 
					
						
							|  |  |  |     if (isupper(display_name[i])) { | 
					
						
							|  |  |  |       all_lower = false; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |   if (all_lower) { | 
					
						
							|  |  |  |     /* For full lowercase string, use title case. */ | 
					
						
							|  |  |  |     bool prevspace = true; | 
					
						
							|  |  |  |     for (int i = 0; display_name[i]; i++) { | 
					
						
							|  |  |  |       if (prevspace) { | 
					
						
							|  |  |  |         display_name[i] = toupper(display_name[i]); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:12:14 +02:00
										 |  |  |       prevspace = isspace(display_name[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * If path begins with "//", strips that and replaces it with `basepath` directory. | 
					
						
							| 
									
										
										
										
											2015-10-17 16:04:54 +11:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note Also converts drive-letter prefix to something more sensible | 
					
						
							|  |  |  |  * if this is a non-drive-letter-based system. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \param path: The path to convert. | 
					
						
							|  |  |  |  * \param basepath: The directory to base relative paths with. | 
					
						
							|  |  |  |  * \return true if the path was relative (started with "//"). | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_abs(char *path, const char *basepath) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |   const bool wasrelative = BLI_path_is_rel(path); | 
					
						
							| 
									
										
										
										
											2008-03-30 16:18:01 +00:00
										 |  |  |   char tmp[FILE_MAX]; | 
					
						
							|  |  |  |   char base[FILE_MAX]; | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-22 14:42:07 +10:00
										 |  |  |   /* without this: "" --> "C:\" */ | 
					
						
							|  |  |  |   if (*path == '\0') { | 
					
						
							|  |  |  |     return wasrelative; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  |   /* we are checking here if we have an absolute path that is not in the current
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  |    * blend file as a lib main - we are basically checking for the case that a | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |    * UNIX root '/' is passed. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |   if (!wasrelative && !BLI_path_is_abs(path)) { | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  |     char *p = path; | 
					
						
							| 
									
										
										
										
											2020-08-26 15:50:48 +02:00
										 |  |  |     BLI_windows_get_default_root_dir(tmp); | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |     /* Get rid of the slashes at the beginning of the path. */ | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |     while (ELEM(*p, '\\', '/')) { | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  |       p++; | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-09-16 11:42:37 +00:00
										 |  |  |     strcat(tmp, p); | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2008-03-30 16:18:01 +00:00
										 |  |  |     BLI_strncpy(tmp, path, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2010-08-12 03:37:45 +00:00
										 |  |  |   BLI_strncpy(tmp, path, sizeof(tmp)); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-01 22:20:53 +11:00
										 |  |  |   /* Check for loading a MS-Windows path on a POSIX system
 | 
					
						
							|  |  |  |    * in this case, there is no use in trying `C:/` since it | 
					
						
							|  |  |  |    * will never exist on a Unix system. | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  |    * | 
					
						
							| 
									
										
										
										
											2021-04-01 22:20:53 +11:00
										 |  |  |    * Add a `/` prefix and lowercase the drive-letter, remove the `:`. | 
					
						
							|  |  |  |    * `C:\foo.JPG` -> `/c/foo.JPG` */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |   if (isalpha(tmp[0]) && (tmp[1] == ':') && ELEM(tmp[2], '\\', '/')) { | 
					
						
							|  |  |  |     tmp[1] = tolower(tmp[0]); /* Replace ':' with drive-letter. */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  |     tmp[0] = '/'; | 
					
						
							| 
									
										
										
										
											2021-04-01 22:20:53 +11:00
										 |  |  |     /* `\` the slash will be converted later. */ | 
					
						
							| 
									
										
										
										
											2008-09-30 04:08:00 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-20 12:18:11 +00:00
										 |  |  |   /* push slashes into unix mode - strings entering this part are
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |    * potentially messed up: having both back- and forward slashes. | 
					
						
							|  |  |  |    * Here we push into one conform direction, and at the end we | 
					
						
							|  |  |  |    * push them into the system specific dir. This ensures uniformity | 
					
						
							|  |  |  |    * of paths and solving some problems (and prevent potential future | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |    * ones) -jesterKing. | 
					
						
							|  |  |  |    * For UNC paths the first characters containing the UNC prefix | 
					
						
							|  |  |  |    * shouldn't be switched as we need to distinguish them from | 
					
						
							|  |  |  |    * paths relative to the .blend file -elubie */ | 
					
						
							| 
									
										
										
										
											2015-06-30 15:18:03 +10:00
										 |  |  |   BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/'); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-05 13:02:00 +00:00
										 |  |  |   /* Paths starting with // will get the blend file as their base,
 | 
					
						
							| 
									
										
										
										
											2012-03-18 07:38:51 +00:00
										 |  |  |    * this isn't standard in any os but is used in blender all over the place */ | 
					
						
							| 
									
										
										
										
											2008-06-14 16:54:46 +00:00
										 |  |  |   if (wasrelative) { | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     const char *lslash; | 
					
						
							|  |  |  |     BLI_strncpy(base, basepath, sizeof(base)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     /* file component is ignored, so don't bother with the trailing slash */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |     BLI_path_normalize(NULL, base); | 
					
						
							|  |  |  |     lslash = BLI_path_slash_rfind(base); | 
					
						
							| 
									
										
										
										
											2015-06-30 15:18:03 +10:00
										 |  |  |     BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/'); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     if (lslash) { | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |       /* length up to and including last "/" */ | 
					
						
							|  |  |  |       const int baselen = (int)(lslash - base) + 1; | 
					
						
							| 
									
										
										
										
											2010-04-25 15:24:18 +00:00
										 |  |  |       /* use path for temp storage here, we copy back over it right away */ | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |       BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |       memcpy(tmp, base, baselen); /* prefix with base up to last "/" */ | 
					
						
							|  |  |  |       BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */ | 
					
						
							|  |  |  |       BLI_strncpy(path, tmp, FILE_MAX);                        /* return as result */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |       /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       BLI_strncpy(path, tmp + 2, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |     /* base ignored */ | 
					
						
							| 
									
										
										
										
											2010-08-12 03:37:45 +00:00
										 |  |  |     BLI_strncpy(path, tmp, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-03-11 01:06:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-05-20 12:18:11 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |   /* skip first two chars, which in case of
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |    * absolute path will be drive:/blabla and | 
					
						
							|  |  |  |    * in case of relpath //blabla/. So relpath
 | 
					
						
							|  |  |  |    * // will be retained, rest will be nice and
 | 
					
						
							|  |  |  |    * shiny win32 backward slashes :) -jesterKing | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2015-06-30 15:18:03 +10:00
										 |  |  |   BLI_str_replace_char(path + 2, '/', '\\'); | 
					
						
							| 
									
										
										
										
											2005-05-20 12:18:11 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-12-01 16:01:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* ensure this is after correcting for path switch */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   BLI_path_normalize(NULL, path); | 
					
						
							| 
									
										
										
										
											2014-12-01 16:01:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   return wasrelative; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-04-08 16:35:13 +10:00
										 |  |  |  * Checks for relative path, expanding them relative to the current working directory. | 
					
						
							|  |  |  |  * Returns true if the expansion was performed. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-04-08 16:35:13 +10:00
										 |  |  |  * \note Should only be called with command line paths. | 
					
						
							|  |  |  |  * This is _not_ something Blender's internal paths support, instead they use the "//" prefix. | 
					
						
							|  |  |  |  * In most cases #BLI_path_abs should be used instead. | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-08 16:35:13 +10:00
										 |  |  | bool BLI_path_abs_from_cwd(char *path, const size_t maxlen) | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(path, 0xff, sizeof(*path) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   bool wasrelative = true; | 
					
						
							|  |  |  |   const int filelen = strlen(path); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) { | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     wasrelative = false; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (filelen >= 2 && path[0] == '/') { | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     wasrelative = false; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   if (wasrelative) { | 
					
						
							| 
									
										
										
										
											2015-10-08 15:05:58 +11:00
										 |  |  |     char cwd[FILE_MAX]; | 
					
						
							|  |  |  |     /* in case the full path to the blend isn't used */ | 
					
						
							|  |  |  |     if (BLI_current_working_dir(cwd, sizeof(cwd))) { | 
					
						
							| 
									
										
										
										
											2011-11-26 04:07:38 +00:00
										 |  |  |       char origpath[FILE_MAX]; | 
					
						
							|  |  |  |       BLI_strncpy(origpath, path, FILE_MAX); | 
					
						
							| 
									
										
										
										
											2015-10-08 15:05:58 +11:00
										 |  |  |       BLI_join_dirfile(path, maxlen, cwd, origpath); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       printf("Could not get the current working directory - $PWD for an unknown reason.\n"); | 
					
						
							| 
									
										
										
										
											2008-09-15 01:32:53 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   return wasrelative; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Tries appending each of the semicolon-separated extensions in the PATHEXT | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * environment variable (Windows-only) onto `name` in turn until such a file is found. | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |  * Returns success/failure. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2015-05-06 06:34:19 +10:00
										 |  |  | bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen) | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  | { | 
					
						
							|  |  |  |   bool retval = false; | 
					
						
							|  |  |  |   int type; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   type = BLI_exists(name); | 
					
						
							|  |  |  |   if ((type == 0) || S_ISDIR(type)) { | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  |     /* typically 3-5, ".EXE", ".BAT"... etc */ | 
					
						
							|  |  |  |     const int ext_max = 12; | 
					
						
							| 
									
										
										
										
											2018-09-05 14:31:10 +10:00
										 |  |  |     const char *ext = BLI_getenv("PATHEXT"); | 
					
						
							| 
									
										
										
										
											2015-06-02 15:38:14 +10:00
										 |  |  |     if (ext) { | 
					
						
							|  |  |  |       const int name_len = strlen(name); | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  |       char *filename = alloca(name_len + ext_max); | 
					
						
							|  |  |  |       char *filename_ext; | 
					
						
							| 
									
										
										
										
											2015-06-02 15:38:14 +10:00
										 |  |  |       const char *ext_next; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-02 15:38:14 +10:00
										 |  |  |       /* null terminated in the loop */ | 
					
						
							|  |  |  |       memcpy(filename, name, name_len); | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  |       filename_ext = filename + name_len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |       do { | 
					
						
							| 
									
										
										
										
											2015-06-02 15:38:14 +10:00
										 |  |  |         int ext_len; | 
					
						
							|  |  |  |         ext_next = strchr(ext, ';'); | 
					
						
							|  |  |  |         ext_len = ext_next ? ((ext_next++) - ext) : strlen(ext); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  |         if (LIKELY(ext_len < ext_max)) { | 
					
						
							|  |  |  |           memcpy(filename_ext, ext, ext_len); | 
					
						
							|  |  |  |           filename_ext[ext_len] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-06 21:02:16 +10:00
										 |  |  |           type = BLI_exists(filename); | 
					
						
							|  |  |  |           if (type && (!S_ISDIR(type))) { | 
					
						
							| 
									
										
										
										
											2015-06-04 16:48:56 +10:00
										 |  |  |             retval = true; | 
					
						
							|  |  |  |             BLI_strncpy(name, filename, maxlen); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-06-02 15:38:14 +10:00
										 |  |  |       } while ((ext = ext_next)); | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     retval = true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif /* WIN32 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * Search for a binary (executable) | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(fullname, 0xff, sizeof(*fullname) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   const char *path; | 
					
						
							|  |  |  |   bool retval = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  |   const char separator = ';'; | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   const char separator = ':'; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 14:31:10 +10:00
										 |  |  |   path = BLI_getenv("PATH"); | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   if (path) { | 
					
						
							|  |  |  |     char filename[FILE_MAX]; | 
					
						
							|  |  |  |     const char *temp; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |     do { | 
					
						
							|  |  |  |       temp = strchr(path, separator); | 
					
						
							|  |  |  |       if (temp) { | 
					
						
							| 
									
										
										
										
											2018-10-11 09:36:43 +11:00
										 |  |  |         memcpy(filename, path, temp - path); | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |         filename[temp - path] = 0; | 
					
						
							|  |  |  |         path = temp + 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2018-10-11 09:36:43 +11:00
										 |  |  |         BLI_strncpy(filename, path, sizeof(filename)); | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |       BLI_path_append(filename, maxlen, name); | 
					
						
							|  |  |  |       if ( | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:34:19 +10:00
										 |  |  |           BLI_path_program_extensions_add_win32(filename, maxlen) | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  | #else
 | 
					
						
							|  |  |  |           BLI_exists(filename) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |       ) { | 
					
						
							|  |  |  |         BLI_strncpy(fullname, filename, maxlen); | 
					
						
							|  |  |  |         retval = true; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } while (temp); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   if (retval == false) { | 
					
						
							|  |  |  |     *fullname = '\0'; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-06 06:05:31 +10:00
										 |  |  |   return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2013-09-23 14:48:28 +00:00
										 |  |  |  * Sets the specified environment variable to the specified value, | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * and clears it if `val == NULL`. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  | void BLI_setenv(const char *env, const char *val) | 
					
						
							| 
									
										
										
										
											2009-07-21 09:26:28 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-21 08:40:30 +00:00
										 |  |  |   /* free windows */ | 
					
						
							| 
									
										
										
										
											2013-09-23 14:48:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-27 15:34:55 -04:00
										 |  |  | #if (defined(WIN32) || defined(WIN64))
 | 
					
						
							| 
									
										
										
										
											2012-03-20 02:17:37 +00:00
										 |  |  |   uputenv(env, val); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 09:26:28 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-02-05 16:23:34 +11:00
										 |  |  |   /* Linux/macOS/BSD */ | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (val) { | 
					
						
							| 
									
										
										
										
											2013-09-23 14:48:28 +00:00
										 |  |  |     setenv(env, val, 1); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2013-09-23 14:48:28 +00:00
										 |  |  |     unsetenv(env); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-07-21 09:26:28 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-04-11 02:18:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 18:44:09 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  * Only set an env var if already not there. | 
					
						
							|  |  |  |  * Like Unix setenv(env, val, 0); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * (not used anywhere). | 
					
						
							| 
									
										
										
										
											2009-10-19 18:44:09 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  | void BLI_setenv_if_new(const char *env, const char *val) | 
					
						
							| 
									
										
										
										
											2009-10-19 18:44:09 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (BLI_getenv(env) == NULL) { | 
					
						
							| 
									
										
										
										
											2009-10-19 18:44:09 +00:00
										 |  |  |     BLI_setenv(env, val); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-10-19 18:44:09 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 14:31:10 +10:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2019-02-11 10:51:25 +11:00
										 |  |  |  * Get an env var, result has to be used immediately. | 
					
						
							| 
									
										
										
										
											2020-09-10 10:18:32 -06:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * On windows #getenv gets its variables from a static copy of the environment variables taken at | 
					
						
							| 
									
										
										
										
											2020-09-10 12:13:22 -06:00
										 |  |  |  * process start-up, causing it to not pick up on environment variables created during runtime. | 
					
						
							|  |  |  |  * This function uses an alternative method to get environment variables that does pick up on | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  |  * runtime environment variables. The result will be UTF-8 encoded. | 
					
						
							| 
									
										
										
										
											2019-02-11 10:51:25 +11:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-09-05 14:46:54 +10:00
										 |  |  | const char *BLI_getenv(const char *env) | 
					
						
							| 
									
										
										
										
											2018-09-05 14:31:10 +10:00
										 |  |  | { | 
					
						
							|  |  |  | #ifdef _MSC_VER
 | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  |   const char *result = NULL; | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |   /* 32767 is the maximum size of the environment variable on windows,
 | 
					
						
							|  |  |  |    * reserve one more character for the zero terminator. */ | 
					
						
							|  |  |  |   static wchar_t buffer[32768]; | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  |   wchar_t *env_16 = alloc_utf16_from_8(env, 0); | 
					
						
							|  |  |  |   if (env_16) { | 
					
						
							|  |  |  |     if (GetEnvironmentVariableW(env_16, buffer, ARRAY_SIZE(buffer))) { | 
					
						
							|  |  |  |       char *res_utf8 = alloc_utf_8_from_16(buffer, 0); | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |       /* Make sure the result is valid, and will fit into our temporary storage buffer. */ | 
					
						
							| 
									
										
										
										
											2020-12-11 12:09:18 -07:00
										 |  |  |       if (res_utf8) { | 
					
						
							|  |  |  |         if (strlen(res_utf8) + 1 < sizeof(buffer)) { | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |           /* We are re-using the utf16 buffer here, since allocating a second static buffer to
 | 
					
						
							|  |  |  |            * contain the UTF-8 version to return would be wasteful. */ | 
					
						
							| 
									
										
										
										
											2020-12-11 12:09:18 -07:00
										 |  |  |           memcpy(buffer, res_utf8, strlen(res_utf8) + 1); | 
					
						
							|  |  |  |           result = (const char *)buffer; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  |         free(res_utf8); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-12-11 11:59:14 -07:00
										 |  |  |   return result; | 
					
						
							| 
									
										
										
										
											2018-09-05 14:31:10 +10:00
										 |  |  | #else
 | 
					
						
							|  |  |  |   return getenv(env); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Ensures that the parent directory of `name` exists. | 
					
						
							| 
									
										
										
										
											2017-04-17 12:04:38 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * \return true on success (i.e. given path now exists on file-system), false otherwise. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-04-17 12:04:38 +02:00
										 |  |  | bool BLI_make_existing_file(const char *name) | 
					
						
							| 
									
										
											  
											
												Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
  all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
  default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
  tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
  easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
  code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
  (pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
  rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
  with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
  done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
  window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
  system should be built from scratch. I can't really understand this code...
  I expect it is not much needed, especially with advanced layer/passes
  control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
  recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
  effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
  to check first the option to render to a Image window, so Blender can become
  a true single-window application. :)
  For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
											
										 
											2006-01-23 22:05:47 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-05 06:26:10 +00:00
										 |  |  |   char di[FILE_MAX]; | 
					
						
							|  |  |  |   BLI_split_dir_part(name, di, sizeof(di)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-29 14:11:19 +01:00
										 |  |  |   /* make if the dir doesn't exist */ | 
					
						
							| 
									
										
										
										
											2017-04-17 12:04:38 +02:00
										 |  |  |   return BLI_dir_create_recursive(di); | 
					
						
							| 
									
										
											  
											
												Giant commit!
A full detailed description of this will be done later... is several days
of work. Here's a summary:
Render:
- Full cleanup of render code, removing *all* globals and bad level calls
  all over blender. Render module is now not called abusive anymore
- API-fied calls to rendering
- Full recode of internal render pipeline. Is now rendering tiles by
  default, prepared for much smarter 'bucket' render later.
- Each thread now can render a full part
- Renders were tested with 4 threads, goes fine, apart from some lookup
  tables in softshadow and AO still
- Rendering is prepared to do multiple layers and passes
- No single 32 bits trick in render code anymore, all 100% floats now.
Writing images/movies
- moved writing images to blender kernel (bye bye 'schrijfplaatje'!)
- made a new Movie handle system, also in kernel. This will enable much
  easier use of movies in Blender
PreviewRender:
- Using new render API, previewrender (in buttons) now uses regular render
  code to generate images.
- new datafile 'preview.blend.c' has the preview scenes in it
- previews get rendered in exact displayed size (1 pixel = 1 pixel)
3D Preview render
- new; press Pkey in 3d window, for a panel that continuously renders
  (pkey is for games, i know... but we dont do that in orange now!)
- this render works nearly identical to buttons-preview render, so it stops
  rendering on any event (mouse, keyboard, etc)
- on moving/scaling the panel, the render code doesn't recreate all geometry
- same for shifting/panning view
- all other operations (now) regenerate the full render database still.
- this is WIP... but big fun, especially for simple scenes!
Compositor
- Using same node system as now in use for shaders, you can composit images
- works pretty straightforward... needs much more options/tools and integration
  with rendering still
- is not threaded yet, nor is so smart to only recalculate changes... will be
  done soon!
- the "Render Result" node will get all layers/passes as output sockets
- The "Output" node renders to a builtin image, which you can view in the Image
  window. (yes, output nodes to render-result, and to files, is on the list!)
The Bad News
- "Unified Render" is removed. It might come back in some stage, but this
  system should be built from scratch. I can't really understand this code...
  I expect it is not much needed, especially with advanced layer/passes
  control
- Panorama render, Field render, Motion blur, is not coded yet... (I had to
  recode every single feature in render, so...!)
- Lens Flare is also not back... needs total revision, might become composit
  effect though (using zbuffer for visibility)
- Part render is gone! (well, thats obvious, its default now).
- The render window is only restored with limited functionality... I am going
  to check first the option to render to a Image window, so Blender can become
  a true single-window application. :)
  For example, the 'Spare render buffer' (jkey) doesnt work.
- Render with border, now default creates a smaller image
- No zbuffers are written yet... on the todo!
- Scons files and MSVC will need work to get compiling again
OK... thats what I can quickly recall. Now go compiling!
											
										 
											2006-01-23 22:05:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Returns in `string` the concatenation of `dir` and `file` (also with `relabase` on the | 
					
						
							|  |  |  |  * front if specified and `dir` begins with "//"). Normalizes all occurrences of path | 
					
						
							|  |  |  |  * separators, including ensuring there is exactly one between the copies of `dir` and `file`, | 
					
						
							|  |  |  |  * and between the copies of `relabase` and `dir`. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * \param relabase: Optional prefix to substitute for "//" on front of `dir`. | 
					
						
							|  |  |  |  * \param string: Area to return result. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-11 15:02:23 +00:00
										 |  |  |   int sl; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-23 05:56:55 +00:00
										 |  |  |   if (string) { | 
					
						
							|  |  |  |     /* ensure this is always set even if dir/file are NULL */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     string[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-23 05:56:55 +00:00
										 |  |  |     if (ELEM(NULL, dir, file)) { | 
					
						
							|  |  |  |       return; /* We don't want any NULLs */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2021-02-05 19:07:03 -08:00
										 |  |  |     return; /* string is NULL, probably shouldn't happen but return anyway */ | 
					
						
							| 
									
										
										
										
											2011-10-23 05:56:55 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |   /* Resolve relative references */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   if (relabase && dir[0] == '/' && dir[1] == '/') { | 
					
						
							|  |  |  |     char *lslash; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     /* Get the file name, chop everything past the last slash (ie. the filename) */ | 
					
						
							|  |  |  |     strcpy(string, relabase); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |     lslash = (char *)BLI_path_slash_rfind(string); | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     if (lslash) { | 
					
						
							|  |  |  |       *(lslash + 1) = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     dir += 2; /* Skip over the relative reference */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') { | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |       BLI_strncpy(string, dir, 3); | 
					
						
							|  |  |  |       dir += 2; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |     else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) { | 
					
						
							|  |  |  |       string[0] = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |     else { /* no drive specified */ | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |            /* first option: get the drive from the relabase if it has one */ | 
					
						
							| 
									
										
										
										
											2014-04-21 16:49:35 +02:00
										 |  |  |       if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') { | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |         BLI_strncpy(string, relabase, 3); | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |         string[2] = '\\'; | 
					
						
							|  |  |  |         string[3] = '\0'; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ | 
					
						
							| 
									
										
										
										
											2020-08-26 15:50:48 +02:00
										 |  |  |         BLI_windows_get_default_root_dir(string); | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |       /* ignore leading slashes */ | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |       while (ELEM(*dir, '/', '\\')) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |         dir++; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2006-08-20 14:41:13 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   strcat(string, dir); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-21 05:46:41 +00:00
										 |  |  |   /* Make sure string ends in one (and only one) slash */ | 
					
						
							| 
									
										
										
										
											2006-02-11 15:02:23 +00:00
										 |  |  |   /* first trim all slashes from the end of the string */ | 
					
						
							|  |  |  |   sl = strlen(string); | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |   while ((sl > 0) && ELEM(string[sl - 1], '/', '\\')) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     string[sl - 1] = '\0'; | 
					
						
							| 
									
										
										
										
											2006-02-11 15:02:23 +00:00
										 |  |  |     sl--; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /* since we've now removed all slashes, put back one slash at the end. */ | 
					
						
							|  |  |  |   strcat(string, "/"); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 00:58:48 +11:00
										 |  |  |   while (ELEM(*file, '/', '\\')) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     /* Trim slashes from the front of file */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |     file++; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   strcat(string, file); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |   /* Push all slashes to the system preferred direction */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   BLI_path_slash_native(string); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | static bool path_extension_check_ex(const char *str, | 
					
						
							|  |  |  |                                     const size_t str_len, | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  |                                     const char *ext, | 
					
						
							|  |  |  |                                     const size_t ext_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BLI_assert(strlen(str) == str_len); | 
					
						
							|  |  |  |   BLI_assert(strlen(ext) == ext_len); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return (((str_len == 0 || ext_len == 0 || ext_len >= str_len) == 0) && | 
					
						
							|  |  |  |           (BLI_strcasecmp(ext, str + str_len - ext_len) == 0)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  | /* does str end with ext. */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_check(const char *str, const char *ext) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  |   return path_extension_check_ex(str, strlen(str), ext, strlen(ext)); | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_check_n(const char *str, ...) | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   const size_t str_len = strlen(str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_list args; | 
					
						
							|  |  |  |   const char *ext; | 
					
						
							|  |  |  |   bool ret = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_start(args, str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while ((ext = (const char *)va_arg(args, void *))) { | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  |     if (path_extension_check_ex(str, str_len, ext, strlen(ext))) { | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  |       ret = true; | 
					
						
							| 
									
										
										
										
											2014-12-01 14:33:38 +01:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ret; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  | /* does str end with any of the suffixes in *ext_array. */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_check_array(const char *str, const char **ext_array) | 
					
						
							| 
									
										
										
										
											2010-08-03 12:34:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  |   const size_t str_len = strlen(str); | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   int i = 0; | 
					
						
							| 
									
										
										
										
											2014-01-31 03:09:01 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   while (ext_array[i]) { | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  |     if (path_extension_check_ex(str, str_len, ext_array[i], strlen(ext_array[i]))) { | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2010-08-03 12:34:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2010-08-03 12:34:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Semicolon separated wildcards, eg: `*.zip;*.py;*.exe` | 
					
						
							|  |  |  |  * does str match any of the semicolon-separated glob patterns in #fnmatch. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   const char *ext_step = ext_fnmatch; | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  |   char pattern[16]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |   while (ext_step[0]) { | 
					
						
							| 
									
										
										
										
											2014-04-27 00:20:55 +10:00
										 |  |  |     const char *ext_next; | 
					
						
							| 
									
										
										
										
											2015-09-07 19:21:12 +02:00
										 |  |  |     size_t len_ext; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     if ((ext_next = strchr(ext_step, ';'))) { | 
					
						
							| 
									
										
										
										
											2015-09-07 19:21:12 +02:00
										 |  |  |       len_ext = ext_next - ext_step + 1; | 
					
						
							| 
									
										
										
										
											2015-09-09 11:02:32 +02:00
										 |  |  |       BLI_strncpy(pattern, ext_step, (len_ext > sizeof(pattern)) ? sizeof(pattern) : len_ext); | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2015-09-09 11:02:32 +02:00
										 |  |  |       len_ext = BLI_strncpy_rlen(pattern, ext_step, sizeof(pattern)); | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) { | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     ext_step += len_ext; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 18:36:37 +00:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-11 12:09:18 -07:00
										 |  |  |  * Does basic validation of the given glob string, to prevent common issues from string | 
					
						
							|  |  |  |  * truncation. | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * For now, only forbids last group to be a wildcard-only one, if there are more than one group | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * (i.e. things like `*.txt;*.cpp;*` are changed to `*.txt;*.cpp;`) | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \returns true if it had to modify given \a ext_fnmatch pattern. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | bool BLI_path_extension_glob_validate(char *ext_fnmatch) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bool only_wildcards = false; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  |   for (size_t i = strlen(ext_fnmatch); i-- > 0;) { | 
					
						
							|  |  |  |     if (ext_fnmatch[i] == ';') { | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |       /* Group separator, we truncate here if we only had wildcards so far.
 | 
					
						
							|  |  |  |        * Otherwise, all is sound and fine. */ | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  |       if (only_wildcards) { | 
					
						
							|  |  |  |         ext_fnmatch[i] = '\0'; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!ELEM(ext_fnmatch[i], '?', '*')) { | 
					
						
							|  |  |  |       /* Non-wildcard char, we can break here and consider the pattern valid. */ | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* So far, only wildcards in last group of the pattern... */ | 
					
						
							|  |  |  |     only_wildcards = true; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |   /* Only one group in the pattern, so even if its only made of wildcard(s),
 | 
					
						
							| 
									
										
										
										
											2019-07-07 15:38:41 +10:00
										 |  |  |    * it is assumed valid. */ | 
					
						
							| 
									
										
										
										
											2018-06-18 12:26:47 +02:00
										 |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-24 06:20:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Removes any existing extension on the end of \a path and appends \a ext. | 
					
						
							|  |  |  |  * \return false if there was no room. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) | 
					
						
							| 
									
										
											  
											
												Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
  or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
  a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
  editing the code directly.
* Functions removed that were only used for sequencer plugin API:
  IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
  IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
  IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
  line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
											
										 
											2010-05-07 15:18:04 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(path, 0xff, sizeof(*path) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   const size_t path_len = strlen(path); | 
					
						
							|  |  |  |   const size_t ext_len = strlen(ext); | 
					
						
							| 
									
										
										
										
											2011-12-21 20:56:49 +00:00
										 |  |  |   ssize_t a; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   for (a = path_len - 1; a >= 0; a--) { | 
					
						
							| 
									
										
										
										
											2014-07-20 01:30:29 +10:00
										 |  |  |     if (ELEM(path[a], '.', '/', '\\')) { | 
					
						
							| 
									
										
											  
											
												Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
  or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
  a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
  editing the code directly.
* Functions removed that were only used for sequencer plugin API:
  IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
  IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
  IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
  line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
											
										 
											2010-05-07 15:18:04 +00:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2011-03-08 08:33:52 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-21 20:56:49 +00:00
										 |  |  |   if ((a < 0) || (path[a] != '.')) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     a = path_len; | 
					
						
							| 
									
										
										
										
											2011-11-15 07:35:28 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (a + ext_len >= maxlen) { | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   memcpy(path + a, ext, ext_len + 1); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2011-10-31 00:23:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Strip's trailing '.'s and adds the extension only when needed | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-06-17 16:13:24 +02:00
										 |  |  | bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) | 
					
						
							| 
									
										
										
										
											2011-10-31 00:23:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(path, 0xff, sizeof(*path) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   const size_t path_len = strlen(path); | 
					
						
							|  |  |  |   const size_t ext_len = strlen(ext); | 
					
						
							| 
									
										
										
										
											2011-12-21 20:56:49 +00:00
										 |  |  |   ssize_t a; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   /* first check the extension is already there */ | 
					
						
							| 
									
										
										
										
											2015-01-26 16:03:11 +01:00
										 |  |  |   if ((ext_len <= path_len) && (STREQ(path + (path_len - ext_len), ext))) { | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     return true; | 
					
						
							| 
									
										
										
										
											2011-10-31 00:23:42 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   for (a = path_len - 1; a >= 0; a--) { | 
					
						
							| 
									
										
										
										
											2011-10-31 00:23:42 +00:00
										 |  |  |     if (path[a] == '.') { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |       path[a] = '\0'; | 
					
						
							| 
									
										
										
										
											2011-10-31 00:23:42 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   a++; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (a + ext_len >= maxlen) { | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   memcpy(path + a, ext, ext_len + 1); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   return true; | 
					
						
							| 
									
										
											  
											
												Merge image related changes from the render branch. This includes the image
tile cache code in imbuf, but it is not hooked up to the render engine.
Imbuf module: some small refactoring and removing a lot of unused or old code
(about 6.5k lines).
* Added a ImFileType struct with callbacks to make adding an file format type,
  or making changes to the API easier.
* Move imbuf init/exit code into IMB_init()/IMB_exit() functions.
* Increased mipmap levels from 10 to 20, you run into this limit already with
  a 2k image.
* Removed hamx, amiga, anim5 format support.
* Removed colormap saving, only simple colormap code now for reading tga.
* Removed gen_dynlibtiff.py, editing this is almost as much work as just
  editing the code directly.
* Functions removed that were only used for sequencer plugin API:
  IMB_anim_nextpic, IMB_clever_double, IMB_antialias, IMB_gamwarp,
  IMB_scalefieldImBuf, IMB_scalefastfieldImBuf, IMB_onethird, IMB_halflace,
  IMB_dit0, IMB_dit2, IMB_cspace
* Write metadata info into OpenEXR images. Can be viewed with the command
  line utility 'exrheader'
For the image tile cache code, see this page:
http://wiki.blender.org/index.php/Dev:2.5/Source/Imaging/ImageTileCache
											
										 
											2010-05-07 15:18:04 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filename) | 
					
						
							| 
									
										
										
										
											2013-08-29 05:34:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(filepath, 0xff, sizeof(*filepath) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   char *c = (char *)BLI_path_slash_rfind(filepath); | 
					
						
							| 
									
										
										
										
											2013-08-29 05:34:58 +00:00
										 |  |  |   if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) { | 
					
						
							|  |  |  |     strcpy(c ? &c[1] : filepath, filename); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-10 00:06:53 +10:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Converts `/foo/bar.txt` to `/foo/` and `bar.txt` | 
					
						
							| 
									
										
										
										
											2019-04-10 00:06:53 +10:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-06-22 10:42:32 -07:00
										 |  |  |  * - Won't change \a string. | 
					
						
							|  |  |  |  * - Won't create any directories. | 
					
						
							| 
									
										
										
										
											2019-04-10 00:06:53 +10:00
										 |  |  |  * - Doesn't use CWD, or deal with relative paths. | 
					
						
							|  |  |  |  * - Only fill's in \a dir and \a file when they are non NULL. | 
					
						
							| 
									
										
										
										
											2021-01-20 15:15:38 +11:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-10-15 03:56:05 +00:00
										 |  |  | void BLI_split_dirfile( | 
					
						
							|  |  |  |     const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen) | 
					
						
							| 
									
										
										
										
											2008-04-26 13:08:57 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(dir, 0xff, sizeof(*dir) * dirlen); | 
					
						
							|  |  |  |   memset(file, 0xff, sizeof(*file) * filelen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   const char *lslash_str = BLI_path_slash_rfind(string); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |   const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-26 13:08:57 +00:00
										 |  |  |   if (dir) { | 
					
						
							|  |  |  |     if (lslash) { | 
					
						
							| 
									
										
										
										
											2019-01-15 23:15:58 +11:00
										 |  |  |       /* +1 to include the slash and the last char */ | 
					
						
							|  |  |  |       BLI_strncpy(dir, string, MIN2(dirlen, lslash + 1)); | 
					
						
							| 
									
										
										
										
											2011-10-15 03:56:05 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2008-04-26 13:08:57 +00:00
										 |  |  |       dir[0] = '\0'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-26 13:08:57 +00:00
										 |  |  |   if (file) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     BLI_strncpy(file, string + lslash, filelen); | 
					
						
							| 
									
										
										
										
											2008-04-26 13:08:57 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-03-28 15:29:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Copies the parent directory part of string into `dir`, max length `dirlen`. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-10-21 02:13:36 +00:00
										 |  |  | void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BLI_split_dirfile(string, dir, NULL, dirlen, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Copies the leaf filename part of string into `file`, max length `filelen`. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-10-21 02:13:36 +00:00
										 |  |  | void BLI_split_file_part(const char *string, char *file, const size_t filelen) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   BLI_split_dirfile(string, NULL, file, 0, filelen); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 15:35:48 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns a pointer to the last extension (e.g. the position of the last period). | 
					
						
							|  |  |  |  * Returns NULL if there is no extension. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const char *BLI_path_extension(const char *filepath) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const char *extension = strrchr(filepath, '.'); | 
					
						
							|  |  |  |   if (extension == NULL) { | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   if (BLI_path_slash_find(extension) != NULL) { | 
					
						
							| 
									
										
										
										
											2019-08-13 15:35:48 +02:00
										 |  |  |     /* There is a path separator in the extension, so the '.' was found in a
 | 
					
						
							|  |  |  |      * directory component and not in the filename. */ | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return extension; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 21:25:06 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Append a filename to a dir, ensuring slash separates. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-09-02 11:19:21 +00:00
										 |  |  | void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) | 
					
						
							| 
									
										
										
										
											2013-07-24 21:25:06 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   size_t dirlen = BLI_strnlen(dst, maxlen); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   /* inline BLI_path_slash_ensure */ | 
					
						
							| 
									
										
										
										
											2013-07-24 21:25:06 +00:00
										 |  |  |   if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) { | 
					
						
							|  |  |  |     dst[dirlen++] = SEP; | 
					
						
							|  |  |  |     dst[dirlen] = '\0'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (dirlen >= maxlen) { | 
					
						
							|  |  |  |     return; /* fills the path */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_strncpy(dst + dirlen, file, maxlen - dirlen); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Simple appending of filename to dir, does not check for valid path! | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * Puts result into `dst`, which may be same area as `dir`. | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-09-02 11:19:21 +00:00
										 |  |  | void BLI_join_dirfile(char *__restrict dst, | 
					
						
							|  |  |  |                       const size_t maxlen, | 
					
						
							|  |  |  |                       const char *__restrict dir, | 
					
						
							|  |  |  |                       const char *__restrict file) | 
					
						
							| 
									
										
										
										
											2007-02-28 21:37:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(dst, 0xff, sizeof(*dst) * maxlen); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   size_t dirlen = BLI_strnlen(dir, maxlen); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 21:25:06 +00:00
										 |  |  |   /* args can't match */ | 
					
						
							|  |  |  |   BLI_assert(!ELEM(dst, dir, file)); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 21:25:06 +00:00
										 |  |  |   if (dirlen == maxlen) { | 
					
						
							|  |  |  |     memcpy(dst, dir, dirlen); | 
					
						
							|  |  |  |     dst[dirlen - 1] = '\0'; | 
					
						
							|  |  |  |     return; /* dir fills the path */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   memcpy(dst, dir, dirlen + 1); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-12 11:18:46 +00:00
										 |  |  |   if (dirlen + 1 >= maxlen) { | 
					
						
							|  |  |  |     return; /* fills the path */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   /* inline BLI_path_slash_ensure */ | 
					
						
							| 
									
										
										
										
											2015-11-27 21:12:42 +01:00
										 |  |  |   if ((dirlen > 0) && !ELEM(dst[dirlen - 1], SEP, ALTSEP)) { | 
					
						
							| 
									
										
										
										
											2012-03-12 06:53:47 +00:00
										 |  |  |     dst[dirlen++] = SEP; | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     dst[dirlen] = '\0'; | 
					
						
							| 
									
										
										
										
											2007-02-28 21:37:14 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-12 11:18:46 +00:00
										 |  |  |   if (dirlen >= maxlen) { | 
					
						
							|  |  |  |     return; /* fills the path */ | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-12 11:18:46 +00:00
										 |  |  |   BLI_strncpy(dst + dirlen, file, maxlen - dirlen); | 
					
						
							| 
									
										
										
										
											2007-02-28 21:37:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Join multiple strings into a path, ensuring only a single path separator between each, | 
					
						
							|  |  |  |  * and trailing slash is kept. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * \note If you want a trailing slash, add `SEP_STR` as the last path argument, | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |  * duplicate slashes will be cleaned up. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-06-17 15:35:00 +02:00
										 |  |  | #ifdef DEBUG_STRSIZE
 | 
					
						
							|  |  |  |   memset(dst, 0xff, sizeof(*dst) * dst_len); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   if (UNLIKELY(dst_len == 0)) { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const size_t dst_last = dst_len - 1; | 
					
						
							|  |  |  |   size_t ofs = BLI_strncpy_rlen(dst, path, dst_len); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   if (ofs == dst_last) { | 
					
						
							|  |  |  |     return ofs; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   /* remove trailing slashes, unless there are _only_ trailing slashes
 | 
					
						
							|  |  |  |    * (allow "//" as the first argument). */ | 
					
						
							|  |  |  |   bool has_trailing_slash = false; | 
					
						
							|  |  |  |   if (ofs != 0) { | 
					
						
							|  |  |  |     size_t len = ofs; | 
					
						
							|  |  |  |     while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { | 
					
						
							|  |  |  |       len -= 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (len != 0) { | 
					
						
							|  |  |  |       ofs = len; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     has_trailing_slash = (path[len] != '\0'); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   va_list args; | 
					
						
							|  |  |  |   va_start(args, path); | 
					
						
							|  |  |  |   while ((path = (const char *)va_arg(args, const char *))) { | 
					
						
							|  |  |  |     has_trailing_slash = false; | 
					
						
							|  |  |  |     const char *path_init = path; | 
					
						
							|  |  |  |     while (ELEM(path[0], SEP, ALTSEP)) { | 
					
						
							|  |  |  |       path++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     size_t len = strlen(path); | 
					
						
							|  |  |  |     if (len != 0) { | 
					
						
							|  |  |  |       while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) { | 
					
						
							|  |  |  |         len -= 1; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |       if (len != 0) { | 
					
						
							|  |  |  |         /* the very first path may have a slash at the end */ | 
					
						
							|  |  |  |         if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) { | 
					
						
							|  |  |  |           dst[ofs++] = SEP; | 
					
						
							|  |  |  |           if (ofs == dst_last) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         has_trailing_slash = (path[len] != '\0'); | 
					
						
							|  |  |  |         if (ofs + len >= dst_last) { | 
					
						
							|  |  |  |           len = dst_last - ofs; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         memcpy(&dst[ofs], path, len); | 
					
						
							|  |  |  |         ofs += len; | 
					
						
							|  |  |  |         if (ofs == dst_last) { | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       has_trailing_slash = (path_init != path); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   va_end(args); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   if (has_trailing_slash) { | 
					
						
							|  |  |  |     if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) { | 
					
						
							|  |  |  |       dst[ofs++] = SEP; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   BLI_assert(ofs <= dst_last); | 
					
						
							|  |  |  |   dst[ofs] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 17:29:48 +11:00
										 |  |  |   return ofs; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2020-12-14 19:04:43 +11:00
										 |  |  |  * like Python's `os.path.basename()` | 
					
						
							| 
									
										
										
										
											2013-03-05 03:17:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \return The pointer into \a path string immediately after last slash, | 
					
						
							|  |  |  |  * or start of \a path if none found. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | const char *BLI_path_basename(const char *path) | 
					
						
							| 
									
										
										
										
											2010-06-05 21:19:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  |   const char *const filename = BLI_path_slash_rfind(path); | 
					
						
							| 
									
										
										
										
											2010-06-05 21:19:59 +00:00
										 |  |  |   return filename ? filename + 1 : path; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-26 11:50:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Get an element of the path at an index, eg: | 
					
						
							|  |  |  |  * "/some/path/file.txt" where an index of... | 
					
						
							|  |  |  |  * - 0 or -3: "some" | 
					
						
							|  |  |  |  * - 1 or -2: "path" | 
					
						
							|  |  |  |  * - 2 or -1: "file.txt" | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Ignores multiple slashes at any point in the path (including start/end). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-05-25 13:22:25 -06:00
										 |  |  | bool BLI_path_name_at_index(const char *__restrict path, | 
					
						
							|  |  |  |                             const int index, | 
					
						
							|  |  |  |                             int *__restrict r_offset, | 
					
						
							|  |  |  |                             int *__restrict r_len) | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   if (index >= 0) { | 
					
						
							|  |  |  |     int index_step = 0; | 
					
						
							|  |  |  |     int prev = -1; | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     while (true) { | 
					
						
							|  |  |  |       const char c = path[i]; | 
					
						
							|  |  |  |       if (ELEM(c, SEP, ALTSEP, '\0')) { | 
					
						
							|  |  |  |         if (prev + 1 != i) { | 
					
						
							|  |  |  |           prev += 1; | 
					
						
							|  |  |  |           if (index_step == index) { | 
					
						
							|  |  |  |             *r_offset = prev; | 
					
						
							|  |  |  |             *r_len = i - prev; | 
					
						
							|  |  |  |             /* printf("!!! %d %d\n", start, end); */ | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           index_step += 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (c == '\0') { | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         prev = i; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       i += 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* negative number, reverse where -1 is the last element */ | 
					
						
							|  |  |  |   int index_step = -1; | 
					
						
							|  |  |  |   int prev = strlen(path); | 
					
						
							|  |  |  |   int i = prev - 1; | 
					
						
							|  |  |  |   while (true) { | 
					
						
							|  |  |  |     const char c = i >= 0 ? path[i] : '\0'; | 
					
						
							|  |  |  |     if (ELEM(c, SEP, ALTSEP, '\0')) { | 
					
						
							|  |  |  |       if (prev - 1 != i) { | 
					
						
							|  |  |  |         i += 1; | 
					
						
							|  |  |  |         if (index_step == index) { | 
					
						
							|  |  |  |           *r_offset = i; | 
					
						
							|  |  |  |           *r_len = prev - i; | 
					
						
							|  |  |  |           return true; | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |         index_step -= 1; | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |       if (c == '\0') { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       prev = i; | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |     i -= 1; | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2017-03-22 19:31:34 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns pointer to the leftmost path separator in string. Not actually used anywhere. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | const char *BLI_path_slash_find(const char *string) | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-27 00:20:55 +10:00
										 |  |  |   const char *const ffslash = strchr(string, '/'); | 
					
						
							|  |  |  |   const char *const fbslash = strchr(string, '\\'); | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (!ffslash) { | 
					
						
							|  |  |  |     return fbslash; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |   if (!fbslash) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     return ffslash; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-03 18:16:06 +10:00
										 |  |  |   return (ffslash < fbslash) ? ffslash : fbslash; | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Returns pointer to the rightmost path separator in string. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | const char *BLI_path_slash_rfind(const char *string) | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  |   const char *const lfslash = strrchr(string, '/'); | 
					
						
							|  |  |  |   const char *const lbslash = strrchr(string, '\\'); | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |   if (!lfslash) { | 
					
						
							|  |  |  |     return lbslash; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-08-07 11:23:02 +02:00
										 |  |  |   if (!lbslash) { | 
					
						
							| 
									
										
										
										
											2019-03-27 13:16:10 +11:00
										 |  |  |     return lfslash; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-17 16:32:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-03 18:16:06 +10:00
										 |  |  |   return (lfslash > lbslash) ? lfslash : lbslash; | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Appends a slash to string if there isn't one there already. | 
					
						
							|  |  |  |  * Returns the new length of the string. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | int BLI_path_slash_ensure(char *string) | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  |   int len = strlen(string); | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |   if (len == 0 || string[len - 1] != SEP) { | 
					
						
							| 
									
										
										
										
											2011-10-11 05:21:24 +00:00
										 |  |  |     string[len] = SEP; | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     string[len + 1] = '\0'; | 
					
						
							|  |  |  |     return len + 1; | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   return len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-04 19:27:51 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Removes the last slash and everything after it to the end of string, if there is one. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_slash_rstrip(char *string) | 
					
						
							| 
									
										
										
										
											2011-09-28 05:53:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  |   int len = strlen(string); | 
					
						
							|  |  |  |   while (len) { | 
					
						
							| 
									
										
										
										
											2012-05-12 15:13:06 +00:00
										 |  |  |     if (string[len - 1] == SEP) { | 
					
						
							|  |  |  |       string[len - 1] = '\0'; | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  |       len--; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:18:31 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2010-10-27 06:41:48 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-26 11:50:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-31 01:40:05 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Changes to the path separators to the native ones for this OS. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-04-07 12:02:21 +10:00
										 |  |  | void BLI_path_slash_native(char *path) | 
					
						
							| 
									
										
										
										
											2014-07-31 01:40:05 +10:00
										 |  |  | { | 
					
						
							|  |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |   if (path && BLI_strnlen(path, 3) > 2) { | 
					
						
							| 
									
										
										
										
											2021-06-10 18:35:35 +02:00
										 |  |  |     BLI_str_replace_char(path + 2, ALTSEP, SEP); | 
					
						
							| 
									
										
										
										
											2014-07-31 01:40:05 +10:00
										 |  |  |   } | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2021-06-10 18:35:35 +02:00
										 |  |  |   BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), ALTSEP, SEP); | 
					
						
							| 
									
										
										
										
											2014-07-31 01:40:05 +10:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | } |