This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/BLI_path_util.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

419 lines
15 KiB
C++
Raw Normal View History

/*
* 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
* of the License, or (at your option) any later version.
*
* 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.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
#pragma once
/** \file
* \ingroup bli
*/
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Sets the specified environment variable to the specified value,
* and clears it if `val == NULL`.
*/
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1);
/**
* Only set an environment variable if already not there.
* Like Unix `setenv(env, val, 0);`
*
* (not used anywhere).
*/
void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1);
/**
* Get an environment variable, result has to be used immediately.
*
* On windows #getenv gets its variables from a static copy of the environment variables taken at
* 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
* runtime environment variables. The result will be UTF-8 encoded.
*/
const char *BLI_getenv(const char *env) ATTR_NONNULL(1);
/**
* 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`.
*
* \param relabase: Optional prefix to substitute for "//" on front of `dir`.
* \param string: Area to return result.
*/
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file);
/**
* Ensures that the parent directory of `name` exists.
*
* \return true on success (i.e. given path now exists on file-system), false otherwise.
*/
bool BLI_make_existing_file(const char *name);
/**
* Converts `/foo/bar.txt` to `/foo/` and `bar.txt`
*
* - Won't change \a string.
* - Won't create any directories.
* - Doesn't use CWD, or deal with relative paths.
* - Only fill's in \a dir and \a file when they are non NULL.
*/
void BLI_split_dirfile(
const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen);
/**
* Copies the parent directory part of string into `dir`, max length `dirlen`.
*/
void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen);
/**
* Copies the leaf filename part of string into `file`, max length `filelen`.
*/
void BLI_split_file_part(const char *string, char *file, const size_t filelen);
/**
* 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) ATTR_NONNULL();
/**
* Append a filename to a dir, ensuring slash separates.
*/
void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
ATTR_NONNULL();
/**
* Simple appending of filename to dir, does not check for valid path!
* Puts result into `dst`, which may be same area as `dir`.
*
* \note Consider using #BLI_path_join for more general path joining
* that de-duplicates separators and can handle an arbitrary number of paths.
*/
void BLI_join_dirfile(char *__restrict dst,
const size_t maxlen,
const char *__restrict dir,
const char *__restrict file) ATTR_NONNULL();
/**
* Join multiple strings into a path, ensuring only a single path separator between each,
* and trailing slash is kept.
*
* \note If you want a trailing slash, add `SEP_STR` as the last path argument,
* duplicate slashes will be cleaned up.
*/
size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path_first, ...)
ATTR_NONNULL(1, 3) ATTR_SENTINEL(0);
/**
* Like Python's `os.path.basename()`
*
* \return The pointer into \a path string immediately after last slash,
* or start of \a path if none found.
*/
const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* 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).
*/
bool BLI_path_name_at_index(const char *__restrict path,
const int index,
int *__restrict r_offset,
int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/** Return true only if #containee_path is contained in #container_path. */
bool BLI_path_contains(const char *container_path,
const char *containee_path) ATTR_WARN_UNUSED_RESULT;
/**
* Returns pointer to the rightmost path separator in string.
*/
const char *BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* Appends a slash to string if there isn't one there already.
* Returns the new length of the string.
*/
int BLI_path_slash_ensure(char *string) ATTR_NONNULL();
/**
* Removes the last slash and everything after it to the end of string, if there is one.
*/
void BLI_path_slash_rstrip(char *string) ATTR_NONNULL();
/**
* Returns pointer to the leftmost path separator in string. Not actually used anywhere.
*/
const char *BLI_path_slash_find(const char *string) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* Changes to the path separators to the native ones for this OS.
*/
void BLI_path_slash_native(char *path) ATTR_NONNULL();
#ifdef _WIN32
bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen);
#endif
/**
* Search for a binary (executable)
*/
bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name);
/**
* \return true when `str` end with `ext` (case insensitive).
*/
bool BLI_path_extension_check(const char *str, const char *ext)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
bool BLI_path_extension_check_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0);
/**
* \return true when `str` ends with any of the suffixes in `ext_array`.
*/
bool BLI_path_extension_check_array(const char *str, const char **ext_array)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* Semicolon separated wildcards, eg: `*.zip;*.py;*.exe`
* does `str` match any of the semicolon-separated glob patterns in #fnmatch.
*/
bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch)
ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* Does basic validation of the given glob string, to prevent common issues from string
* truncation.
*
* For now, only forbids last group to be a wildcard-only one, if there are more than one group
* (i.e. things like `*.txt;*.cpp;*` are changed to `*.txt;*.cpp;`)
*
* \returns true if it had to modify given \a ext_fnmatch pattern.
*/
bool BLI_path_extension_glob_validate(char *ext_fnmatch) ATTR_NONNULL();
/**
* Removes any existing extension on the end of \a path and appends \a ext.
* \return false if there was no room.
*/
bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
/**
* Strip's trailing '.'s and adds the extension only when needed
*/
bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ATTR_NONNULL();
bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filename) ATTR_NONNULL();
/**
* Looks for a sequence of decimal digits in string, preceding any filename extension,
* returning the integer value if found, or 0 if not.
*
* \param string: String to scan.
* \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.
* \param r_num_len: Optional to return number of digits found.
*/
int BLI_path_sequence_decode(const char *string,
char *head,
char *tail,
unsigned short *r_num_len);
/**
* 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.
*/
void BLI_path_sequence_encode(
char *string, const char *head, const char *tail, unsigned short numlen, int pic);
/**
* Remove redundant characters from \a path and optionally make absolute.
*
* \param relabase: The path this is relative to, or ignored when NULL.
* \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.
*/
void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2);
/**
* Cleanup file-path ensuring a trailing slash.
*
* \note Same as #BLI_path_normalize but adds a trailing slash.
*/
void BLI_path_normalize_dir(const char *relabase, char *dir) ATTR_NONNULL(2);
/**
* Make given name safe to be used in paths.
*
* \return true if \a fname was changed, false otherwise.
*
* For now, simply replaces reserved chars (as listed in
* https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words )
* by underscores ('_').
*
* \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,
* but supported by all decent file-systems/operating-systems around.
*
* \note On Windows, it also ensures there is no '.' (dot char) at the end of the file,
* this can lead to issues.
*
* \note On Windows, it also checks for forbidden names
* (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx ).
*/
bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1);
/**
* Make given path OS-safe.
*
* \return true if \a path was changed, false otherwise.
*/
bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
/**
* Go back one directory.
*
* Replaces path with the path of its parent directory, returning true if
* it was able to find a parent directory within the path.
*/
bool BLI_path_parent_dir(char *path) ATTR_NONNULL();
/**
* Go back until the directory is found.
*
* Strips off nonexistent (or non-accessible) sub-directories from the end of `dir`,
* leaving the path of the lowest-level directory that does exist and we can read.
*/
bool BLI_path_parent_dir_until_exists(char *path) ATTR_NONNULL();
/**
* If path begins with "//", strips that and replaces it with `basepath` directory.
*
* \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 "//").
*/
2014-02-01 00:51:53 +11:00
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL();
/**
* Replaces "#" character sequence in last slash-separated component of `path`
* with frame as decimal integer, with leading zeroes as necessary, to make digits digits.
*/
2014-02-01 00:51:53 +11:00
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL();
/**
* Replaces "#" character sequence in last slash-separated component of `path`
* with sta and end as decimal integers, with leading zeroes as necessary, to make digits
* digits each, with a hyphen in-between.
*/
2014-02-01 00:51:53 +11:00
bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL();
/**
* Get the frame from a filename formatted by blender's frame scheme
*/
bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL();
void BLI_path_frame_strip(char *path, char *ext) ATTR_NONNULL();
/**
* Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
*/
2014-02-01 00:51:53 +11:00
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
/**
* Checks for relative path, expanding them relative to the current working directory.
* Returns true if the expansion was performed.
*
* \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.
*/
bool BLI_path_abs_from_cwd(char *path, const size_t maxlen) ATTR_NONNULL();
/**
* 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.
*/
2014-02-01 00:51:53 +11:00
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL();
/**
* Does path begin with the special "//" prefix that Blender uses to indicate
* a path relative to the .blend file.
*/
2014-02-01 00:51:53 +11:00
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
/**
* Return true if the path is a UNC share.
*/
bool BLI_path_is_unc(const char *path);
/**
* Creates a display string from path to be used menus and the user interface.
* Like `bpy.path.display_name()`.
*/
Application Templates: make templates more prominent in the UI. The goal here is to make app templates usable for default templates that we can ship with Blender. These only have a custom startup.blend currently and so are quite limited compared to app templates that fully customize Blender. But still it seems like the same kind of concept where we should be sharing the code and UI. It is useful to be able to save a startup.blend per template, and I can imagine some scripting being useful in the future as well. Changes made: * File > New and Ctrl+N now list the templates, replacing a separate Application Templates menu that was not as easy to discover. * File menu now shows name of active template above Save Startup File and Load Factory Settings to indicate these are saved/loaded per template. * The "Default" template was renamed to "General". * Workspaces can now be added from any of the template startup.blend files when clicking the (+) button in the topbar. * User preferences are now fully shared between app templates, unless the template includes a custom userpref.blend. I think this will be useful in general, not all app templates need their own keymaps for example. * Previously Save User Preferences would save the current app template and then Blender would start using that template by default. I've disabled this, to me it seems it was unintentional, or at least not clear at all that saving user preferences also makes the current Differential Revision: https://developer.blender.org/D3690
2018-08-28 15:12:14 +02:00
void BLI_path_to_display_name(char *display_name, int maxlen, const char *name) ATTR_NONNULL();
#if defined(WIN32)
void BLI_path_normalize_unc_16(wchar_t *path_16);
void BLI_path_normalize_unc(char *path_16, int maxlen);
#endif
/**
* Appends a suffix to the string, fitting it before the extension
*
* string = Foo.png, suffix = 123, separator = _
* Foo.png -> Foo_123.png
*
* \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
* \return true if succeeded
*/
bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char *sep)
ATTR_NONNULL();
/* Path string comparisons: case-insensitive for Windows, case-sensitive otherwise. */
#if defined(WIN32)
# define BLI_path_cmp BLI_strcasecmp
# define BLI_path_ncmp BLI_strncasecmp
#else
# define BLI_path_cmp strcmp
# define BLI_path_ncmp strncmp
#endif
/* These values need to be hard-coded in structs, dna does not recognize defines */
/* also defined in `DNA_space_types.h`. */
#ifndef FILE_MAXDIR
# define FILE_MAXDIR 768
# define FILE_MAXFILE 256
# define FILE_MAX 1024
#endif
#ifdef WIN32
# define SEP '\\'
# define ALTSEP '/'
# define SEP_STR "\\"
# define ALTSEP_STR "/"
#else
# define SEP '/'
# define ALTSEP '\\'
# define SEP_STR "/"
# define ALTSEP_STR "\\"
#endif
/* Parent and current dir helpers. */
#define FILENAME_PARENT ".."
#define FILENAME_CURRENT "."
/* Avoid calling `strcmp` on one or two chars! */
#define FILENAME_IS_PARENT(_n) (((_n)[0] == '.') && ((_n)[1] == '.') && ((_n)[2] == '\0'))
#define FILENAME_IS_CURRENT(_n) (((_n)[0] == '.') && ((_n)[1] == '\0'))
#define FILENAME_IS_CURRPAR(_n) \
(((_n)[0] == '.') && (((_n)[1] == '\0') || (((_n)[1] == '.') && ((_n)[2] == '\0'))))
#ifdef __cplusplus
}
#endif