Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_color_mix.hh2
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h2
-rw-r--r--source/blender/blenlib/BLI_path_util.h20
-rw-r--r--source/blender/blenlib/BLI_string_utils.h393
-rw-r--r--source/blender/blenlib/BLI_uvproject.h2
-rw-r--r--source/blender/blenlib/intern/fileops.c2
-rw-r--r--source/blender/blenlib/intern/kdtree_impl.h6
-rw-r--r--source/blender/blenlib/intern/list_sort_impl.h49
-rw-r--r--source/blender/blenlib/intern/path_util.c211
-rw-r--r--source/blender/blenlib/intern/string_utils.c14
-rw-r--r--source/blender/blenlib/intern/uvproject.c2
-rw-r--r--source/blender/blenlib/tests/BLI_path_util_test.cc502
12 files changed, 936 insertions, 269 deletions
diff --git a/source/blender/blenlib/BLI_color_mix.hh b/source/blender/blenlib/BLI_color_mix.hh
index 322da2bf112..55989669f70 100644
--- a/source/blender/blenlib/BLI_color_mix.hh
+++ b/source/blender/blenlib/BLI_color_mix.hh
@@ -76,7 +76,7 @@ struct FloatTraits {
static inline BlendType max(BlendType a, BlendType b)
{
- return min_ff(a, b);
+ return max_ff(a, b);
}
/* Discretizes in steps of 1.0 / range */
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 7e1b7c2ba56..538474f58b6 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -624,7 +624,7 @@ void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float n
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3]);
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target) \
- BLI_space_transform_from_matrices((data), (local)->obmat, (target)->obmat)
+ BLI_space_transform_from_matrices((data), (local)->object_to_world, (target)->object_to_world)
/** \} */
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index d4d2ddead71..4ea059391b6 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -68,8 +68,15 @@ const char *BLI_path_extension(const char *filepath) ATTR_NONNULL();
/**
* Append a filename to a dir, ensuring slash separates.
+ * \return The new length of `dst`.
*/
-void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file)
+size_t BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file)
+ ATTR_NONNULL();
+/**
+ * A version of #BLI_path_append that ensures a trailing slash if there is space in `dst`.
+ * \return The new length of `dst`.
+ */
+size_t BLI_path_append_dir(char *__restrict dst, size_t maxlen, const char *__restrict dir)
ATTR_NONNULL();
/**
@@ -195,7 +202,10 @@ const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_
* - 1 or -2: `path`
* - 2 or -1: `file.txt`
*
- * Ignores multiple slashes at any point in the path (including start/end).
+ * Ignored elements in the path:
+ * - Multiple slashes at any point in the path (including start/end).
+ * - Single '.' in the path: `/./` except for the beginning of the path
+ * where it's used to signify a $PWD relative path.
*/
bool BLI_path_name_at_index(const char *__restrict path,
int index,
@@ -218,7 +228,7 @@ const char *BLI_path_slash_rfind(const char *string) ATTR_NONNULL() ATTR_WARN_UN
* 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();
+int BLI_path_slash_ensure(char *string, size_t string_maxlen) ATTR_NONNULL(1);
/**
* Removes the last slash and everything after it to the end of string, if there is one.
*/
@@ -314,7 +324,7 @@ void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2);
*
* \note Same as #BLI_path_normalize but adds a trailing slash.
*/
-void BLI_path_normalize_dir(const char *relabase, char *dir) ATTR_NONNULL(2);
+void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen) ATTR_NONNULL(2);
/**
* Make given name safe to be used in paths.
@@ -357,6 +367,8 @@ bool BLI_path_make_safe(char *path) ATTR_NONNULL(1);
*
* Replaces path with the path of its parent directory, returning true if
* it was able to find a parent directory within the path.
+ *
+ * On success, the resulting path will always have a trailing slash.
*/
bool BLI_path_parent_dir(char *path) ATTR_NONNULL();
/**
diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h
index df82e94ae2e..936e892a9e2 100644
--- a/source/blender/blenlib/BLI_string_utils.h
+++ b/source/blender/blenlib/BLI_string_utils.h
@@ -48,33 +48,6 @@ void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, size
void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, size_t str_len);
/**
- * Join strings, return newly allocated string.
- */
-char *BLI_string_join_array(char *result,
- size_t result_len,
- const char *strings[],
- uint strings_len) ATTR_NONNULL();
-/**
- * A version of #BLI_string_join that takes a separator which can be any character including '\0'.
- */
-char *BLI_string_join_array_by_sep_char(char *result,
- size_t result_len,
- char sep,
- const char *strings[],
- uint strings_len) ATTR_NONNULL();
-
-/**
- * Join an array of strings into a newly allocated, null terminated string.
- */
-char *BLI_string_join_arrayN(const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT
- ATTR_NONNULL();
-/**
- * A version of #BLI_string_joinN that takes a separator which can be any character including '\0'.
- */
-char *BLI_string_join_array_by_sep_charN(char sep,
- const char *strings[],
- uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-/**
* A version of #BLI_string_join_array_by_sep_charN that takes a table array.
* The new location of each string is written into this array.
*/
@@ -82,17 +55,7 @@ char *BLI_string_join_array_by_sep_char_with_tableN(char sep,
char *table[],
const char *strings[],
uint strings_len) ATTR_NONNULL();
-/**
- * Take multiple arguments, pass as (array, length).
- */
-#define BLI_string_join(result, result_len, ...) \
- BLI_string_join_array( \
- result, result_len, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
-#define BLI_string_joinN(...) \
- BLI_string_join_arrayN(((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
-#define BLI_string_join_by_sep_charN(sep, ...) \
- BLI_string_join_array_by_sep_charN( \
- sep, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
+
#define BLI_string_join_by_sep_char_with_tableN(sep, table, ...) \
BLI_string_join_array_by_sep_char_with_tableN( \
sep, table, ((const char *[]){__VA_ARGS__}), VA_NARGS_COUNT(__VA_ARGS__))
@@ -149,6 +112,360 @@ bool BLI_uniquename(struct ListBase *list,
int name_offset,
size_t name_len);
+/* Expand array functions. */
+
+/* Intentionally no comma after `_BLI_STRING_ARGS_0` to allow it to be empty. */
+#define _BLI_STRING_ARGS_1 _BLI_STRING_ARGS_0 const char *a
+#define _BLI_STRING_ARGS_2 _BLI_STRING_ARGS_1, const char *b
+#define _BLI_STRING_ARGS_3 _BLI_STRING_ARGS_2, const char *c
+#define _BLI_STRING_ARGS_4 _BLI_STRING_ARGS_3, const char *d
+#define _BLI_STRING_ARGS_5 _BLI_STRING_ARGS_4, const char *e
+#define _BLI_STRING_ARGS_6 _BLI_STRING_ARGS_5, const char *f
+#define _BLI_STRING_ARGS_7 _BLI_STRING_ARGS_6, const char *g
+#define _BLI_STRING_ARGS_8 _BLI_STRING_ARGS_7, const char *h
+#define _BLI_STRING_ARGS_9 _BLI_STRING_ARGS_8, const char *i
+#define _BLI_STRING_ARGS_10 _BLI_STRING_ARGS_9, const char *j
+
+/* ------------------------------------------------------------------------- */
+/** \name Implement: `BLI_string_join(..)`
+ * \{ */
+
+#define _BLI_STRING_ARGS_0 char *__restrict dst, const size_t dst_len,
+
+/**
+ * Join strings, return the length of the resulting string.
+ */
+size_t BLI_string_join_array(char *result,
+ size_t result_len,
+ const char *strings[],
+ uint strings_len) ATTR_NONNULL();
+
+#define BLI_string_join(...) VA_NARGS_CALL_OVERLOAD(_BLI_string_join_, __VA_ARGS__)
+
+BLI_INLINE size_t _BLI_string_join_3(_BLI_STRING_ARGS_1) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_4(_BLI_STRING_ARGS_2) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_5(_BLI_STRING_ARGS_3) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_6(_BLI_STRING_ARGS_4) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_7(_BLI_STRING_ARGS_5) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_8(_BLI_STRING_ARGS_6) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_9(_BLI_STRING_ARGS_7) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_10(_BLI_STRING_ARGS_8) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_11(_BLI_STRING_ARGS_9) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_12(_BLI_STRING_ARGS_10) ATTR_NONNULL();
+
+BLI_INLINE size_t _BLI_string_join_3(_BLI_STRING_ARGS_1)
+{
+ const char *string_array[] = {a};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_4(_BLI_STRING_ARGS_2)
+{
+ const char *string_array[] = {a, b};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_5(_BLI_STRING_ARGS_3)
+{
+ const char *string_array[] = {a, b, c};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_6(_BLI_STRING_ARGS_4)
+{
+ const char *string_array[] = {a, b, c, d};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_7(_BLI_STRING_ARGS_5)
+{
+ const char *string_array[] = {a, b, c, d, e};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_8(_BLI_STRING_ARGS_6)
+{
+ const char *string_array[] = {a, b, c, d, e, f};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_9(_BLI_STRING_ARGS_7)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_10(_BLI_STRING_ARGS_8)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_11(_BLI_STRING_ARGS_9)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_12(_BLI_STRING_ARGS_10)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i, j};
+ return BLI_string_join_array(dst, dst_len, string_array, ARRAY_SIZE(string_array));
+}
+
+#undef _BLI_STRING_ARGS_0
+
+/** \} */
+
+/* ------------------------------------------------------------------------- */
+/** \name Implement: `BLI_string_joinN(..)`
+ * \{ */
+
+/**
+ * Join an array of strings into a newly allocated, null terminated string.
+ */
+char *BLI_string_join_arrayN(const char *strings[], uint strings_len) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
+
+#define BLI_string_joinN(...) VA_NARGS_CALL_OVERLOAD(_BLI_string_joinN_, __VA_ARGS__)
+
+#define _BLI_STRING_ARGS_0
+
+BLI_INLINE char *_BLI_string_joinN_1(_BLI_STRING_ARGS_1) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_2(_BLI_STRING_ARGS_2) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_3(_BLI_STRING_ARGS_3) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_4(_BLI_STRING_ARGS_4) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_5(_BLI_STRING_ARGS_5) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_6(_BLI_STRING_ARGS_6) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_7(_BLI_STRING_ARGS_7) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_8(_BLI_STRING_ARGS_8) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_9(_BLI_STRING_ARGS_9) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_joinN_10(_BLI_STRING_ARGS_10) ATTR_NONNULL();
+
+BLI_INLINE char *_BLI_string_joinN_1(_BLI_STRING_ARGS_1)
+{
+ const char *string_array[] = {a};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_2(_BLI_STRING_ARGS_2)
+{
+ const char *string_array[] = {a, b};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_3(_BLI_STRING_ARGS_3)
+{
+ const char *string_array[] = {a, b, c};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_4(_BLI_STRING_ARGS_4)
+{
+ const char *string_array[] = {a, b, c, d};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_5(_BLI_STRING_ARGS_5)
+{
+ const char *string_array[] = {a, b, c, d, e};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_6(_BLI_STRING_ARGS_6)
+{
+ const char *string_array[] = {a, b, c, d, e, f};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_7(_BLI_STRING_ARGS_7)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_8(_BLI_STRING_ARGS_8)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_9(_BLI_STRING_ARGS_9)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_joinN_10(_BLI_STRING_ARGS_10)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i, j};
+ return BLI_string_join_arrayN(string_array, ARRAY_SIZE(string_array));
+}
+
+#undef _BLI_STRING_ARGS_0
+
+/** \} */
+
+/* ------------------------------------------------------------------------- */
+/** \name Implement: `BLI_string_join_by_sep_char(..)`
+ * \{ */
+
+/**
+ * A version of #BLI_string_join_array that takes a separator which can be any character
+ * including '\0'.
+ */
+size_t BLI_string_join_array_by_sep_char(char *result,
+ size_t result_len,
+ char sep,
+ const char *strings[],
+ uint strings_len) ATTR_NONNULL();
+
+#define BLI_string_join_by_sep_char(...) \
+ VA_NARGS_CALL_OVERLOAD(_BLI_string_join_by_sep_char_, __VA_ARGS__)
+
+#define _BLI_STRING_ARGS_0 char *__restrict dst, const size_t dst_len, const char sep,
+
+BLI_INLINE size_t _BLI_string_join_by_sep_char_4(_BLI_STRING_ARGS_1) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_5(_BLI_STRING_ARGS_2) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_6(_BLI_STRING_ARGS_3) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_7(_BLI_STRING_ARGS_4) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_8(_BLI_STRING_ARGS_5) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_9(_BLI_STRING_ARGS_6) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_10(_BLI_STRING_ARGS_7) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_11(_BLI_STRING_ARGS_8) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_12(_BLI_STRING_ARGS_9) ATTR_NONNULL();
+BLI_INLINE size_t _BLI_string_join_by_sep_char_13(_BLI_STRING_ARGS_10) ATTR_NONNULL();
+
+BLI_INLINE size_t _BLI_string_join_by_sep_char_4(_BLI_STRING_ARGS_1)
+{
+ const char *string_array[] = {a};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_5(_BLI_STRING_ARGS_2)
+{
+ const char *string_array[] = {a, b};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_6(_BLI_STRING_ARGS_3)
+{
+ const char *string_array[] = {a, b, c};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_7(_BLI_STRING_ARGS_4)
+{
+ const char *string_array[] = {a, b, c, d};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_8(_BLI_STRING_ARGS_5)
+{
+ const char *string_array[] = {a, b, c, d, e};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_9(_BLI_STRING_ARGS_6)
+{
+ const char *string_array[] = {a, b, c, d, e, f};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_10(_BLI_STRING_ARGS_7)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_11(_BLI_STRING_ARGS_8)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_12(_BLI_STRING_ARGS_9)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE size_t _BLI_string_join_by_sep_char_13(_BLI_STRING_ARGS_10)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i, j};
+ return BLI_string_join_array_by_sep_char(
+ dst, dst_len, sep, string_array, ARRAY_SIZE(string_array));
+}
+
+#undef _BLI_STRING_ARGS_0
+
+/** \} */
+
+/* ------------------------------------------------------------------------- */
+/** \name Implement: `BLI_string_join_by_sep_charN(..)`
+ * \{ */
+
+/**
+ * A version of #BLI_string_join_by_sep_char that takes a separator which can be any character
+ * including '\0'.
+ */
+char *BLI_string_join_array_by_sep_charN(char sep,
+ const char *strings[],
+ uint strings_len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+#define BLI_string_join_by_sep_charN(...) \
+ VA_NARGS_CALL_OVERLOAD(_BLI_string_join_by_sep_charN_, __VA_ARGS__)
+
+#define _BLI_STRING_ARGS_0 const char sep,
+
+BLI_INLINE char *_BLI_string_join_by_sep_charN_2(_BLI_STRING_ARGS_1) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_3(_BLI_STRING_ARGS_2) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_4(_BLI_STRING_ARGS_3) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_5(_BLI_STRING_ARGS_4) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_6(_BLI_STRING_ARGS_5) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_7(_BLI_STRING_ARGS_6) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_8(_BLI_STRING_ARGS_7) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_9(_BLI_STRING_ARGS_8) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_10(_BLI_STRING_ARGS_9) ATTR_NONNULL();
+BLI_INLINE char *_BLI_string_join_by_sep_charN_11(_BLI_STRING_ARGS_10) ATTR_NONNULL();
+
+BLI_INLINE char *_BLI_string_join_by_sep_charN_2(_BLI_STRING_ARGS_1)
+{
+ const char *string_array[] = {a};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_3(_BLI_STRING_ARGS_2)
+{
+ const char *string_array[] = {a, b};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_4(_BLI_STRING_ARGS_3)
+{
+ const char *string_array[] = {a, b, c};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_5(_BLI_STRING_ARGS_4)
+{
+ const char *string_array[] = {a, b, c, d};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_6(_BLI_STRING_ARGS_5)
+{
+ const char *string_array[] = {a, b, c, d, e};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_7(_BLI_STRING_ARGS_6)
+{
+ const char *string_array[] = {a, b, c, d, e, f};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_8(_BLI_STRING_ARGS_7)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_9(_BLI_STRING_ARGS_8)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_10(_BLI_STRING_ARGS_9)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+BLI_INLINE char *_BLI_string_join_by_sep_charN_11(_BLI_STRING_ARGS_10)
+{
+ const char *string_array[] = {a, b, c, d, e, f, g, h, i, j};
+ return BLI_string_join_array_by_sep_charN(sep, string_array, ARRAY_SIZE(string_array));
+}
+
+/** \} */
+
+#undef _BLI_STRING_ARGS_0
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_uvproject.h b/source/blender/blenlib/BLI_uvproject.h
index 75f39de6b7f..a94fd796121 100644
--- a/source/blender/blenlib/BLI_uvproject.h
+++ b/source/blender/blenlib/BLI_uvproject.h
@@ -15,7 +15,7 @@ struct ProjCameraInfo;
/**
* Create UV info from the camera, needs to be freed.
*
- * \param rotmat: can be `obedit->obmat` when uv project is used.
+ * \param rotmat: can be `obedit->object_to_world` when uv project is used.
* \param winx, winy: can be from `scene->r.xsch / ysch`.
*/
struct ProjCameraInfo *BLI_uvproject_camera_info(struct Object *ob,
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index c8acae533bd..f5516bf344a 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -401,7 +401,7 @@ static bool delete_recursive(const char *dir)
/* dir listing produces dir path without trailing slash... */
BLI_strncpy(path, fl->path, sizeof(path));
- BLI_path_slash_ensure(path);
+ BLI_path_slash_ensure(path, sizeof(path));
if (delete_recursive(path)) {
err = true;
diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h
index 6614f1bf964..f7993eb5adc 100644
--- a/source/blender/blenlib/intern/kdtree_impl.h
+++ b/source/blender/blenlib/intern/kdtree_impl.h
@@ -11,9 +11,9 @@
#include "BLI_strict_flags.h"
#include "BLI_utildefines.h"
-#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
-#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
-#define BLI_kdtree_nd_(id) _CONCAT(KDTREE_PREFIX_ID, _##id)
+#define _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
+#define _BLI_KDTREE_CONCAT(MACRO_ARG1, MACRO_ARG2) _BLI_KDTREE_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
+#define BLI_kdtree_nd_(id) _BLI_KDTREE_CONCAT(KDTREE_PREFIX_ID, _##id)
typedef struct KDTreeNode_head {
uint left, right;
diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h
index e1b93986f4a..7c38fc60b29 100644
--- a/source/blender/blenlib/intern/list_sort_impl.h
+++ b/source/blender/blenlib/intern/list_sort_impl.h
@@ -47,24 +47,25 @@
#endif
#ifdef SORT_IMPL_USE_THUNK
-# define THUNK_APPEND1(a, thunk) a, thunk
-# define THUNK_PREPEND2(thunk, a, b) thunk, a, b
+# define BLI_LIST_THUNK_APPEND1(a, thunk) a, thunk
+# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) thunk, a, b
#else
-# define THUNK_APPEND1(a, thunk) a
-# define THUNK_PREPEND2(thunk, a, b) a, b
+# define BLI_LIST_THUNK_APPEND1(a, thunk) a
+# define BLI_LIST_THUNK_PREPEND2(thunk, a, b) a, b
#endif
-#define _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
-#define _CONCAT(MACRO_ARG1, MACRO_ARG2) _CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
-#define _SORT_PREFIX(id) _CONCAT(SORT_IMPL_FUNC, _##id)
+#define _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2) MACRO_ARG1##MACRO_ARG2
+#define _BLI_LIST_SORT_CONCAT(MACRO_ARG1, MACRO_ARG2) \
+ _BLI_LIST_SORT_CONCAT_AUX(MACRO_ARG1, MACRO_ARG2)
+#define _BLI_LIST_SORT_PREFIX(id) _BLI_LIST_SORT_CONCAT(SORT_IMPL_FUNC, _##id)
/* local identifiers */
-#define SortInfo _SORT_PREFIX(SortInfo)
-#define CompareFn _SORT_PREFIX(CompareFn)
-#define init_sort_info _SORT_PREFIX(init_sort_info)
-#define merge_lists _SORT_PREFIX(merge_lists)
-#define sweep_up _SORT_PREFIX(sweep_up)
-#define insert_list _SORT_PREFIX(insert_list)
+#define SortInfo _BLI_LIST_SORT_PREFIX(SortInfo)
+#define CompareFn _BLI_LIST_SORT_PREFIX(CompareFn)
+#define init_sort_info _BLI_LIST_SORT_PREFIX(init_sort_info)
+#define merge_lists _BLI_LIST_SORT_PREFIX(merge_lists)
+#define sweep_up _BLI_LIST_SORT_PREFIX(sweep_up)
+#define insert_list _BLI_LIST_SORT_PREFIX(insert_list)
typedef int (*CompareFn)(
#ifdef SORT_IMPL_USE_THUNK
@@ -159,7 +160,7 @@ BLI_INLINE list_node *merge_lists(list_node *first,
list_node *list = NULL;
list_node **pos = &list;
while (first && second) {
- if (func(THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
+ if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(first), SORT_ARG(second))) > 0) {
*pos = second;
second = second->next;
}
@@ -181,7 +182,7 @@ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned in
{
unsigned int i;
for (i = si->min_rank; i < upto; i++) {
- list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
si->ranks[i] = NULL;
}
return list;
@@ -225,17 +226,19 @@ BLI_INLINE void insert_list(struct SortInfo *si, list_node *list, unsigned int r
// printf("Rank '%d' should not exceed " STRINGIFY(MAX_RANKS), rank);
rank = MAX_RANKS;
}
- list = merge_lists(sweep_up(si, NULL, si->n_ranks), list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(
+ sweep_up(si, NULL, si->n_ranks), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
for (i = si->n_ranks; i < rank; i++) {
si->ranks[i] = NULL;
}
}
else {
if (rank) {
- list = merge_lists(sweep_up(si, NULL, rank), list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(
+ sweep_up(si, NULL, rank), list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
}
for (i = rank; i < si->n_ranks && si->ranks[i]; i++) {
- list = merge_lists(si->ranks[i], list, THUNK_APPEND1(si->func, si->thunk));
+ list = merge_lists(si->ranks[i], list, BLI_LIST_THUNK_APPEND1(si->func, si->thunk));
si->ranks[i] = NULL;
}
}
@@ -281,7 +284,7 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
list_node *next = list->next;
list_node *tail = next->next;
- if (func(THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
+ if (func(BLI_LIST_THUNK_PREPEND2(thunk, SORT_ARG(list), SORT_ARG(next))) > 0) {
next->next = list;
next = list;
list = list->next;
@@ -296,8 +299,8 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
return sweep_up(&si, list, si.n_ranks);
}
-#undef _CONCAT_AUX
-#undef _CONCAT
+#undef _BLI_LIST_SORT_CONCAT_AUX
+#undef _BLI_LIST_SORT_CONCAT
#undef _SORT_PREFIX
#undef SortInfo
@@ -310,6 +313,6 @@ BLI_INLINE list_node *list_sort_do(list_node *list,
#undef list_node
#undef list_sort_do
-#undef THUNK_APPEND1
-#undef THUNK_PREPEND2
+#undef BLI_LIST_THUNK_APPEND1
+#undef BLI_LIST_THUNK_PREPEND2
#undef SORT_ARG
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index afe8c3cc033..d13f3fe5ced 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -153,6 +153,19 @@ void BLI_path_normalize(const char *relabase, char *path)
*/
#ifdef WIN32
+
+ while ((start = strstr(path, "\\.\\"))) {
+ eind = start + strlen("\\.\\") - 1;
+ memmove(start, eind, strlen(eind) + 1);
+ }
+
+ /* remove two consecutive backslashes, but skip the UNC prefix,
+ * which needs to be preserved */
+ while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
+ eind = start + strlen("\\\\") - 1;
+ memmove(start, eind, strlen(eind) + 1);
+ }
+
while ((start = strstr(path, "\\..\\"))) {
eind = start + strlen("\\..\\") - 1;
a = start - path - 1;
@@ -170,18 +183,18 @@ void BLI_path_normalize(const char *relabase, char *path)
}
}
- while ((start = strstr(path, "\\.\\"))) {
- eind = start + strlen("\\.\\") - 1;
+#else
+
+ while ((start = strstr(path, "/./"))) {
+ eind = start + (3 - 1) /* strlen("/./") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
- /* remove two consecutive backslashes, but skip the UNC prefix,
- * which needs to be preserved */
- while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
- eind = start + strlen("\\\\") - 1;
+ while ((start = strstr(path, "//"))) {
+ eind = start + (2 - 1) /* strlen("//") - 1 */;
memmove(start, eind, strlen(eind) + 1);
}
-#else
+
while ((start = strstr(path, "/../"))) {
a = start - path - 1;
if (a > 0) {
@@ -206,19 +219,10 @@ void BLI_path_normalize(const char *relabase, char *path)
}
}
- while ((start = strstr(path, "/./"))) {
- eind = start + (3 - 1) /* strlen("/./") - 1 */;
- memmove(start, eind, strlen(eind) + 1);
- }
-
- while ((start = strstr(path, "//"))) {
- eind = start + (2 - 1) /* strlen("//") - 1 */;
- memmove(start, eind, strlen(eind) + 1);
- }
#endif
}
-void BLI_path_normalize_dir(const char *relabase, char *dir)
+void BLI_path_normalize_dir(const char *relabase, char *dir, size_t dir_maxlen)
{
/* Would just create an unexpected "/" path, just early exit entirely. */
if (dir[0] == '\0') {
@@ -226,7 +230,7 @@ void BLI_path_normalize_dir(const char *relabase, char *dir)
}
BLI_path_normalize(relabase, dir);
- BLI_path_slash_ensure(dir);
+ BLI_path_slash_ensure(dir, dir_maxlen);
}
bool BLI_filename_make_safe_ex(char *fname, bool allow_tokens)
@@ -622,18 +626,28 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
bool BLI_path_parent_dir(char *path)
{
- const char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
- char tmp[FILE_MAX + 4];
-
- BLI_path_join(tmp, sizeof(tmp), path, parent_dir);
- BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */
-
- if (!BLI_path_extension_check(tmp, parent_dir)) {
- strcpy(path, tmp); /* We assume the parent directory is always shorter. */
- return true;
+ /* Use #BLI_path_name_at_index instead of checking if the strings ends with `parent_dir`
+ * to ensure the logic isn't confused by:
+ * - Directory names that happen to end with `..`.
+ * - When `path` is empty, the contents will be `../`
+ * which would cause checking for a tailing `/../` fail.
+ * Extracting the span of the final directory avoids both these issues. */
+ int tail_ofs = 0, tail_len = 0;
+ if (!BLI_path_name_at_index(path, -1, &tail_ofs, &tail_len)) {
+ return false;
+ }
+ if (tail_len == 1) {
+ /* Last path is ".", as normalize should remove this, it's safe to assume failure.
+ * This happens when the input a single period (possibly with slashes before or after). */
+ if (path[tail_ofs] == '.') {
+ return false;
+ }
}
- return false;
+ /* Input paths should already be normalized if `..` is part of the path. */
+ BLI_assert(!((tail_len == 2) && (path[tail_ofs] == '.') && (path[tail_ofs + 1] == '.')));
+ path[tail_ofs] = '\0';
+ return true;
}
bool BLI_path_parent_dir_until_exists(char *dir)
@@ -1431,21 +1445,34 @@ const char *BLI_path_extension(const char *filepath)
return extension;
}
-void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
+size_t BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file)
{
size_t dirlen = BLI_strnlen(dst, maxlen);
- /* inline BLI_path_slash_ensure */
+ /* Inline #BLI_path_slash_ensure. */
if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
dst[dirlen++] = SEP;
dst[dirlen] = '\0';
}
if (dirlen >= maxlen) {
- return; /* fills the path */
+ return dirlen; /* fills the path */
}
- BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
+ return dirlen + BLI_strncpy_rlen(dst + dirlen, file, maxlen - dirlen);
+}
+
+size_t BLI_path_append_dir(char *__restrict dst, const size_t maxlen, const char *__restrict dir)
+{
+ size_t dirlen = BLI_path_append(dst, maxlen, dir);
+ if (dirlen + 1 < maxlen) {
+ /* Inline #BLI_path_slash_ensure. */
+ if ((dirlen > 0) && (dst[dirlen - 1] != SEP)) {
+ dst[dirlen++] = SEP;
+ dst[dirlen] = '\0';
+ }
+ }
+ return dirlen;
}
size_t BLI_path_join_array(char *__restrict dst,
@@ -1469,14 +1496,36 @@ size_t BLI_path_join_array(char *__restrict dst,
return ofs;
}
+#ifdef WIN32
+ /* Special case "//" for relative paths, don't use separator #SEP
+ * as this has a special meaning on both WIN32 & UNIX.
+ * Without this check joining `"//", "path"`. results in `"//\path"`. */
+ if (ofs != 0) {
+ size_t i;
+ for (i = 0; i < ofs; i++) {
+ if (dst[i] != '/') {
+ break;
+ }
+ }
+ if (i == ofs) {
+ /* All slashes, keep them as-is, and join the remaining path array. */
+ return path_array_num > 1 ?
+ BLI_path_join_array(
+ dst + ofs, dst_len - ofs, &path_array[1], path_array_num - 1) :
+ ofs;
+ }
+ }
+#endif
+
/* Remove trailing slashes, unless there are *only* trailing slashes
* (allow `//` or `//some_path` 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)) {
+ while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
+
if (len != 0) {
ofs = len;
}
@@ -1487,18 +1536,18 @@ size_t BLI_path_join_array(char *__restrict dst,
path = path_array[path_index];
has_trailing_slash = false;
const char *path_init = path;
- while (ELEM(path[0], SEP, ALTSEP)) {
+ while (path[0] == SEP) {
path++;
}
size_t len = strlen(path);
if (len != 0) {
- while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ while ((len != 0) && (path[len - 1] == SEP)) {
len -= 1;
}
if (len != 0) {
/* the very first path may have a slash at the end */
- if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) {
+ if (ofs && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
if (ofs == dst_last) {
break;
@@ -1521,7 +1570,7 @@ size_t BLI_path_join_array(char *__restrict dst,
}
if (has_trailing_slash) {
- if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) {
+ if ((ofs != dst_last) && (ofs != 0) && (dst[ofs - 1] != SEP)) {
dst[ofs++] = SEP;
}
}
@@ -1538,53 +1587,64 @@ const char *BLI_path_basename(const char *path)
return filename ? filename + 1 : path;
}
-bool BLI_path_name_at_index(const char *__restrict path,
- const int index,
- int *__restrict r_offset,
- int *__restrict r_len)
+static bool path_name_at_index_forward(const char *__restrict path,
+ const int index,
+ int *__restrict r_offset,
+ int *__restrict r_len)
{
- 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;
+ BLI_assert(index >= 0);
+ int index_step = 0;
+ int prev = -1;
+ int i = 0;
+ while (true) {
+ const char c = path[i];
+ if (ELEM(c, SEP, '\0')) {
+ if (prev + 1 != i) {
+ prev += 1;
+ /* Skip '/./' (behave as if they don't exist). */
+ if (!((i - prev == 1) && (prev != 0) && (path[prev] == '.'))) {
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;
+ if (c == '\0') {
+ break;
+ }
+ prev = i;
}
- return false;
+ i += 1;
}
+ return false;
+}
- /* negative number, reverse where -1 is the last element */
+static bool path_name_at_index_backward(const char *__restrict path,
+ const int index,
+ int *__restrict r_offset,
+ int *__restrict r_len)
+{
+ /* Negative number, reverse where -1 is the last element. */
+ BLI_assert(index < 0);
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 (ELEM(c, SEP, '\0')) {
if (prev - 1 != i) {
i += 1;
- if (index_step == index) {
- *r_offset = i;
- *r_len = prev - i;
- return true;
+ /* Skip '/./' (behave as if they don't exist). */
+ if (!((prev - i == 1) && (i != 0) && (path[i] == '.'))) {
+ if (index_step == index) {
+ *r_offset = i;
+ *r_len = prev - i;
+ return true;
+ }
+ index_step -= 1;
}
- index_step -= 1;
}
if (c == '\0') {
break;
@@ -1596,6 +1656,15 @@ bool BLI_path_name_at_index(const char *__restrict path,
return false;
}
+bool BLI_path_name_at_index(const char *__restrict path,
+ const int index,
+ int *__restrict r_offset,
+ int *__restrict r_len)
+{
+ return (index >= 0) ? path_name_at_index_forward(path, index, r_offset, r_len) :
+ path_name_at_index_backward(path, index, r_offset, r_len);
+}
+
bool BLI_path_contains(const char *container_path, const char *containee_path)
{
char container_native[PATH_MAX];
@@ -1624,7 +1693,7 @@ bool BLI_path_contains(const char *container_path, const char *containee_path)
/* Add a trailing slash to prevent same-prefix directories from matching.
* e.g. "/some/path" doesn't contain "/some/path_lib". */
- BLI_path_slash_ensure(container_native);
+ BLI_path_slash_ensure(container_native, sizeof(container_native));
return BLI_str_startswith(containee_native, container_native);
}
@@ -1659,13 +1728,17 @@ const char *BLI_path_slash_rfind(const char *string)
return (lfslash > lbslash) ? lfslash : lbslash;
}
-int BLI_path_slash_ensure(char *string)
+int BLI_path_slash_ensure(char *string, size_t string_maxlen)
{
int len = strlen(string);
+ BLI_assert(len < string_maxlen);
if (len == 0 || string[len - 1] != SEP) {
- string[len] = SEP;
- string[len + 1] = '\0';
- return len + 1;
+ /* Avoid unlikely buffer overflow. */
+ if (len + 1 < string_maxlen) {
+ string[len] = SEP;
+ string[len + 1] = '\0';
+ return len + 1;
+ }
}
return len;
}
diff --git a/source/blender/blenlib/intern/string_utils.c b/source/blender/blenlib/intern/string_utils.c
index 0b9baaff3e9..27734d2f429 100644
--- a/source/blender/blenlib/intern/string_utils.c
+++ b/source/blender/blenlib/intern/string_utils.c
@@ -344,10 +344,10 @@ bool BLI_uniquename(
*
* \{ */
-char *BLI_string_join_array(char *result,
- size_t result_len,
- const char *strings[],
- uint strings_len)
+size_t BLI_string_join_array(char *result,
+ size_t result_len,
+ const char *strings[],
+ uint strings_len)
{
char *c = result;
char *c_end = &result[result_len - 1];
@@ -358,10 +358,10 @@ char *BLI_string_join_array(char *result,
}
}
*c = '\0';
- return c;
+ return (size_t)(c - result);
}
-char *BLI_string_join_array_by_sep_char(
+size_t BLI_string_join_array_by_sep_char(
char *result, size_t result_len, char sep, const char *strings[], uint strings_len)
{
char *c = result;
@@ -378,7 +378,7 @@ char *BLI_string_join_array_by_sep_char(
}
}
*c = '\0';
- return c;
+ return (size_t)(c - result);
}
char *BLI_string_join_arrayN(const char *strings[], uint strings_len)
diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c
index 347166bd57d..0398bf0b3fe 100644
--- a/source/blender/blenlib/intern/uvproject.c
+++ b/source/blender/blenlib/intern/uvproject.c
@@ -129,7 +129,7 @@ ProjCameraInfo *BLI_uvproject_camera_info(Object *ob, float rotmat[4][4], float
uci.camsize = uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale;
/* account for scaled cameras */
- copy_m4_m4(uci.caminv, ob->obmat);
+ copy_m4_m4(uci.caminv, ob->object_to_world);
normalize_m4(uci.caminv);
if (invert_m4(uci.caminv)) {
diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc
index 89e537235db..9d5422d62ff 100644
--- a/source/blender/blenlib/tests/BLI_path_util_test.cc
+++ b/source/blender/blenlib/tests/BLI_path_util_test.cc
@@ -9,69 +9,166 @@
#include "BLI_string.h"
/* -------------------------------------------------------------------- */
-/* tests */
+/** \name Local Utilities
+ * \{ */
-/* BLI_path_normalize */
-#ifndef _WIN32
-TEST(path_util, Clean)
+static void str_replace_char_with_relative_exception(char *str, char src, char dst)
{
- /* "/./" -> "/" */
- {
- char path[FILE_MAX] = "/a/./b/./c/./";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/c/", path);
+ /* Always keep "//" or more leading slashes (special meaning). */
+ if (src == '/') {
+ if (str[0] == '/' && str[1] == '/') {
+ str += 2;
+ while (*str == '/') {
+ str++;
+ }
+ }
}
+ BLI_str_replace_char(str, src, dst);
+}
- {
- char path[FILE_MAX] = "/./././";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/", path);
+static char *str_replace_char_strdup(const char *str, char src, char dst)
+{
+ if (str == nullptr) {
+ return nullptr;
}
+ char *str_dupe = strdup(str);
+ BLI_str_replace_char(str_dupe, src, dst);
+ return str_dupe;
+}
- {
- char path[FILE_MAX] = "/a/./././b/";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/", path);
- }
+/** \} */
- /* "//" -> "/" */
- {
- char path[FILE_MAX] = "a////";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("a/", path);
- }
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_normalize
+ * \{ */
- if (false) /* FIXME */
- {
- char path[FILE_MAX] = "./a////";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("./a/", path);
- }
+#define NORMALIZE_WITH_BASEDIR(input, input_base, output) \
+ { \
+ char path[FILE_MAX] = input; \
+ const char *input_base_test = input_base; \
+ if (SEP == '\\') { \
+ str_replace_char_with_relative_exception(path, '/', '\\'); \
+ input_base_test = str_replace_char_strdup(input_base_test, '/', '\\'); \
+ } \
+ BLI_path_normalize(input_base_test, path); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ if (input_base_test) { \
+ free((void *)input_base_test); \
+ } \
+ } \
+ EXPECT_STREQ(output, path); \
+ } \
+ ((void)0)
- /* "foo/bar/../" -> "foo/" */
- {
- char path[FILE_MAX] = "/a/b/c/../../../";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/", path);
- }
+#define NORMALIZE(input, output) NORMALIZE_WITH_BASEDIR(input, nullptr, output)
- {
- char path[FILE_MAX] = "/a/../a/b/../b/c/../c/";
- BLI_path_normalize(nullptr, path);
- EXPECT_STREQ("/a/b/c/", path);
- }
+/* #BLI_path_normalize: "/./" -> "/" */
+TEST(path_util, Clean_Dot)
+{
+ NORMALIZE("/./", "/");
+ NORMALIZE("/a/./b/./c/./", "/a/b/c/");
+ NORMALIZE("/./././", "/");
+ NORMALIZE("/a/./././b/", "/a/b/");
+}
+/* #BLI_path_normalize: complex "/./" -> "/", "//" -> "/", "./path/../" -> "./". */
+TEST(path_util, Clean_Complex)
+{
+ NORMALIZE("/a/./b/./c/./.././.././", "/a/");
+ NORMALIZE("/a//.//b//.//c//.//..//.//..//.//", "/a/");
+}
+/* #BLI_path_normalize: "//" -> "/" */
+TEST(path_util, Clean_DoubleSlash)
+{
+ NORMALIZE("//", "//"); /* Exception, double forward slash. */
+ NORMALIZE(".//", "./");
+ NORMALIZE("a////", "a/");
+ NORMALIZE("./a////", "./a/");
+}
+/* #BLI_path_normalize: "foo/bar/../" -> "foo/" */
+TEST(path_util, Clean_Parent)
+{
+ NORMALIZE("/a/b/c/../../../", "/");
+ NORMALIZE("/a/../a/b/../b/c/../c/", "/a/b/c/");
+ NORMALIZE_WITH_BASEDIR("//../", "/a/b/c/", "/a/b/");
+}
- {
- char path[FILE_MAX] = "//../";
- BLI_path_normalize("/a/b/c/", path);
- EXPECT_STREQ("/a/b/", path);
- }
+#undef NORMALIZE_WITH_BASEDIR
+#undef NORMALIZE
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_parent_dir
+ * \{ */
+
+#define PARENT_DIR(input, output) \
+ { \
+ char path[FILE_MAX] = input; \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ } \
+ BLI_path_parent_dir(path); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ } \
+ EXPECT_STREQ(output, path); \
+ } \
+ ((void)0)
+
+TEST(path_util, ParentDir_Simple)
+{
+ PARENT_DIR("/a/b/", "/a/");
+ PARENT_DIR("/a/b", "/a/");
+ PARENT_DIR("/a", "/");
}
-#endif
+
+TEST(path_util, ParentDir_NOP)
+{
+ PARENT_DIR("/", "/");
+ PARENT_DIR("", "");
+ PARENT_DIR(".", ".");
+ PARENT_DIR("./", "./");
+ PARENT_DIR(".//", ".//");
+ PARENT_DIR("./.", "./.");
+}
+
+TEST(path_util, ParentDir_TrailingPeriod)
+{
+ /* Ensure trailing dots aren't confused with parent path. */
+ PARENT_DIR("/.../.../.../", "/.../.../");
+ PARENT_DIR("/.../.../...", "/.../.../");
+
+ PARENT_DIR("/a../b../c../", "/a../b../");
+ PARENT_DIR("/a../b../c..", "/a../b../");
+
+ PARENT_DIR("/a./b./c./", "/a./b./");
+ PARENT_DIR("/a./b./c.", "/a./b./");
+}
+
+TEST(path_util, ParentDir_Complex)
+{
+ PARENT_DIR("./a/", "./");
+ PARENT_DIR("./a", "./");
+ PARENT_DIR("../a/", "../");
+ PARENT_DIR("../a", "../");
+}
+
+#undef PARENT_DIR
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_name_at_index
+ * \{ */
#define AT_INDEX(str_input, index_input, str_expect) \
{ \
char path[] = str_input; \
+ /* Test input assumes forward slash, support back-slash on WIN32. */ \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ } \
const char *expect = str_expect; \
int index_output, len_output; \
const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
@@ -87,7 +184,6 @@ TEST(path_util, Clean)
} \
((void)0)
-/* BLI_path_name_at_index */
TEST(path_util, NameAtIndex_Single)
{
AT_INDEX("/a", 0, "a");
@@ -163,24 +259,82 @@ TEST(path_util, NameAtIndex_MiscNeg)
AT_INDEX("/how/now/brown/cow/", 4, nullptr);
}
+#define TEST_STR "./a/./b/./c/."
+
+TEST(path_util, NameAtIndex_SingleDot)
+{
+ AT_INDEX(TEST_STR, 0, ".");
+ AT_INDEX(TEST_STR, 1, "a");
+ AT_INDEX(TEST_STR, 2, "b");
+ AT_INDEX(TEST_STR, 3, "c");
+ AT_INDEX(TEST_STR, 4, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotNeg)
+{
+ AT_INDEX(TEST_STR, -5, nullptr);
+ AT_INDEX(TEST_STR, -4, ".");
+ AT_INDEX(TEST_STR, -3, "a");
+ AT_INDEX(TEST_STR, -2, "b");
+ AT_INDEX(TEST_STR, -1, "c");
+}
+
+#undef TEST_STR
+
+#define TEST_STR ".//a//.//b//.//c//.//"
+
+TEST(path_util, NameAtIndex_SingleDotDoubleSlash)
+{
+ AT_INDEX(TEST_STR, 0, ".");
+ AT_INDEX(TEST_STR, 1, "a");
+ AT_INDEX(TEST_STR, 2, "b");
+ AT_INDEX(TEST_STR, 3, "c");
+ AT_INDEX(TEST_STR, 4, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotDoubleSlashNeg)
+{
+ AT_INDEX(TEST_STR, -5, nullptr);
+ AT_INDEX(TEST_STR, -4, ".");
+ AT_INDEX(TEST_STR, -3, "a");
+ AT_INDEX(TEST_STR, -2, "b");
+ AT_INDEX(TEST_STR, -1, "c");
+}
+
+#undef TEST_STR
+
+TEST(path_util, NameAtIndex_SingleDotSeries)
+{
+ AT_INDEX("abc/././/././xyz", 0, "abc");
+ AT_INDEX("abc/././/././xyz", 1, "xyz");
+ AT_INDEX("abc/././/././xyz", 2, nullptr);
+}
+
+TEST(path_util, NameAtIndex_SingleDotSeriesNeg)
+{
+ AT_INDEX("abc/././/././xyz", -3, nullptr);
+ AT_INDEX("abc/././/././xyz", -2, "abc");
+ AT_INDEX("abc/././/././xyz", -1, "xyz");
+}
+
TEST(path_util, NameAtIndex_MiscComplex)
{
AT_INDEX("how//now/brown/cow", 0, "how");
- AT_INDEX("//how///now\\/brown/cow", 1, "now");
- AT_INDEX("/how/now\\//brown\\/cow", 2, "brown");
- AT_INDEX("/how/now/brown/cow//\\", 3, "cow");
- AT_INDEX("/how/now/brown/\\cow", 4, nullptr);
- AT_INDEX("how/now/brown/\\cow\\", 4, nullptr);
+ AT_INDEX("//how///now//brown/cow", 1, "now");
+ AT_INDEX("/how/now///brown//cow", 2, "brown");
+ AT_INDEX("/how/now/brown/cow///", 3, "cow");
+ AT_INDEX("/how/now/brown//cow", 4, nullptr);
+ AT_INDEX("how/now/brown//cow/", 4, nullptr);
}
TEST(path_util, NameAtIndex_MiscComplexNeg)
{
AT_INDEX("how//now/brown/cow", -4, "how");
- AT_INDEX("//how///now\\/brown/cow", -3, "now");
- AT_INDEX("/how/now\\//brown\\/cow", -2, "brown");
- AT_INDEX("/how/now/brown/cow//\\", -1, "cow");
- AT_INDEX("/how/now/brown/\\cow", -5, nullptr);
- AT_INDEX("how/now/brown/\\cow\\", -5, nullptr);
+ AT_INDEX("//how///now//brown/cow", -3, "now");
+ AT_INDEX("/how/now///brown//cow", -2, "brown");
+ AT_INDEX("/how/now/brown/cow///", -1, "cow");
+ AT_INDEX("/how/now/brown//cow", -5, nullptr);
+ AT_INDEX("how/now/brown//cow/", -5, nullptr);
}
TEST(path_util, NameAtIndex_NoneComplex)
@@ -201,21 +355,59 @@ TEST(path_util, NameAtIndex_NoneComplexNeg)
#undef AT_INDEX
-#define JOIN(str_expect, out_size, ...) \
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_join
+ * \{ */
+
+/* For systems with `/` path separator (non WIN32). */
+#define JOIN_FORWARD_SLASH(str_expect, out_size, ...) \
{ \
const char *expect = str_expect; \
char result[(out_size) + 1024]; \
- /* check we don't write past the last byte */ \
+ /* Check we don't write past the last byte. */ \
result[out_size] = '\0'; \
BLI_path_join(result, out_size, __VA_ARGS__); \
- /* simplify expected string */ \
+ EXPECT_STREQ(result, expect); \
+ EXPECT_EQ(result[out_size], '\0'); \
+ } \
+ ((void)0)
+
+/* For systems with `\` path separator (WIN32).
+ * Perform additional manipulation to behave as if input arguments used `\` separators.
+ * Needed since #BLI_path_join uses native slashes. */
+#define JOIN_BACK_SLASH(str_expect, out_size, ...) \
+ { \
+ const char *expect = str_expect; \
+ char result[(out_size) + 1024]; \
+ const char *input_forward_slash[] = {__VA_ARGS__}; \
+ char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \
+ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
+ input_back_slash[i] = strdup(input_forward_slash[i]); \
+ BLI_str_replace_char(input_back_slash[i], '/', '\\'); \
+ } \
+ /* Check we don't write past the last byte. */ \
+ result[out_size] = '\0'; \
+ BLI_path_join_array(result, \
+ out_size, \
+ const_cast<const char **>(input_back_slash), \
+ ARRAY_SIZE(input_back_slash)); \
BLI_str_replace_char(result, '\\', '/'); \
EXPECT_STREQ(result, expect); \
EXPECT_EQ(result[out_size], '\0'); \
+ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
+ free(input_back_slash[i]); \
+ } \
} \
((void)0)
-/* BLI_path_join */
+#ifdef WIN32
+# define JOIN JOIN_BACK_SLASH
+#else
+# define JOIN JOIN_FORWARD_SLASH
+#endif
+
TEST(path_util, JoinNop)
{
JOIN("", 100, "");
@@ -293,9 +485,9 @@ TEST(path_util, JoinTruncateLong)
TEST(path_util, JoinComplex)
{
- JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
- JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
- JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
+ JOIN("/a/b/c/d/e/f/g/", 100, "/", "a/b", "//////c/d", "", "e", "f", "g//");
+ JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "aa/bb", "//////cc/dd", "", "ee", "ff", "gg//");
+ JOIN("1/2/3/", 100, "1", "////////", "", "2", "3///");
}
TEST(path_util, JoinRelativePrefix)
@@ -306,8 +498,15 @@ TEST(path_util, JoinRelativePrefix)
}
#undef JOIN
+#undef JOIN_BACK_SLASH
+#undef JOIN_FORWARD_SLASH
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame
+ * \{ */
-/* BLI_path_frame */
TEST(path_util, Frame)
{
bool ret;
@@ -384,7 +583,12 @@ TEST(path_util, Frame)
}
}
-/* BLI_split_dirfile */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_split_dirfile
+ * \{ */
+
TEST(path_util, SplitDirfile)
{
{
@@ -440,6 +644,12 @@ TEST(path_util, SplitDirfile)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_strip
+ * \{ */
+
#define PATH_FRAME_STRIP(input_path, expect_path, expect_ext) \
{ \
char path[FILE_MAX]; \
@@ -451,7 +661,6 @@ TEST(path_util, SplitDirfile)
} \
((void)0)
-/* BLI_path_frame_strip */
TEST(path_util, PathFrameStrip)
{
PATH_FRAME_STRIP("", "", "");
@@ -463,6 +672,12 @@ TEST(path_util, PathFrameStrip)
}
#undef PATH_FRAME_STRIP
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_extension_check
+ * \{ */
+
#define PATH_EXTENSION_CHECK(input_path, input_ext, expect_ext) \
{ \
const bool ret = BLI_path_extension_check(input_path, input_ext); \
@@ -475,7 +690,6 @@ TEST(path_util, PathFrameStrip)
} \
((void)0)
-/* BLI_path_extension_check */
TEST(path_util, PathExtensionCheck)
{
PATH_EXTENSION_CHECK("a/b/c.exe", ".exe", ".exe");
@@ -501,6 +715,12 @@ TEST(path_util, PathExtensionCheck)
}
#undef PATH_EXTENSION_CHECK
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_check_chars
+ * \{ */
+
#define PATH_FRAME_CHECK_CHARS(input_path, expect_hasChars) \
{ \
const bool ret = BLI_path_frame_check_chars(input_path); \
@@ -513,7 +733,6 @@ TEST(path_util, PathExtensionCheck)
} \
((void)0)
-/* BLI_path_frame_check_chars */
TEST(path_util, PathFrameCheckChars)
{
PATH_FRAME_CHECK_CHARS("a#", true);
@@ -533,6 +752,12 @@ TEST(path_util, PathFrameCheckChars)
}
#undef PATH_FRAME_CHECK_CHARS
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_range
+ * \{ */
+
#define PATH_FRAME_RANGE(input_path, sta, end, digits, expect_outpath) \
{ \
char path[FILE_MAX]; \
@@ -549,7 +774,6 @@ TEST(path_util, PathFrameCheckChars)
} \
((void)0)
-/* BLI_path_frame_range */
TEST(path_util, PathFrameRange)
{
int dummy = -1;
@@ -565,6 +789,12 @@ TEST(path_util, PathFrameRange)
}
#undef PATH_FRAME_RANGE
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_frame_get
+ * \{ */
+
#define PATH_FRAME_GET(input_path, expect_frame, expect_numdigits, expect_pathisvalid) \
{ \
char path[FILE_MAX]; \
@@ -582,7 +812,6 @@ TEST(path_util, PathFrameRange)
} \
((void)0)
-/* BLI_path_frame_get */
TEST(path_util, PathFrameGet)
{
PATH_FRAME_GET("001.avi", 1, 3, true);
@@ -594,7 +823,12 @@ TEST(path_util, PathFrameGet)
}
#undef PATH_FRAME_GET
-/* BLI_path_extension */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_extension
+ * \{ */
+
TEST(path_util, PathExtension)
{
EXPECT_EQ(nullptr, BLI_path_extension("some.def/file"));
@@ -608,62 +842,88 @@ TEST(path_util, PathExtension)
EXPECT_STREQ(".001", BLI_path_extension("Text.001"));
}
-/* BLI_path_rel. */
-#ifndef _WIN32
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_rel
+ * \{ */
-# define PATH_REL(abs_path, ref_path, rel_path) \
- { \
- char path[FILE_MAX]; \
- BLI_strncpy(path, abs_path, sizeof(path)); \
- BLI_path_rel(path, ref_path); \
- EXPECT_STREQ(rel_path, path); \
+#define PATH_REL(abs_path, ref_path, rel_path) \
+ { \
+ char path[FILE_MAX]; \
+ const char *ref_path_test = ref_path; \
+ BLI_strncpy(path, abs_path, sizeof(path)); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '/', '\\'); \
+ ref_path_test = str_replace_char_strdup(ref_path_test, '/', '\\'); \
+ } \
+ BLI_path_rel(path, ref_path_test); \
+ if (SEP == '\\') { \
+ BLI_str_replace_char(path, '\\', '/'); \
+ free((void *)ref_path_test); \
} \
- void(0)
+ EXPECT_STREQ(rel_path, path); \
+ } \
+ void(0)
-TEST(path_util, PathRelPath)
+#ifdef WIN32
+# define ABS_PREFIX "C:"
+#else
+# define ABS_PREFIX ""
+#endif
+
+TEST(path_util, PathRelPath_Simple)
{
- PATH_REL("/foo/bar/blender.blend", "/foo/bar/", "//blender.blend");
- PATH_REL("/foo/bar/blender.blend", "/foo/bar", "//bar/blender.blend");
+ PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar/", "//blender.blend");
+}
- /* Check for potential buffer overflows. */
- {
- char abs_path_in[FILE_MAX];
- abs_path_in[0] = '/';
- for (int i = 1; i < FILE_MAX - 1; i++) {
- abs_path_in[i] = 'A';
- }
- abs_path_in[FILE_MAX - 1] = '\0';
- char abs_path_out[FILE_MAX];
- abs_path_out[0] = '/';
- abs_path_out[1] = '/';
- for (int i = 2; i < FILE_MAX - 1; i++) {
- abs_path_out[i] = 'A';
- }
- abs_path_out[FILE_MAX - 1] = '\0';
- PATH_REL(abs_path_in, "/", abs_path_out);
-
- const char *ref_path_in = "/foo/bar/";
- const size_t ref_path_in_len = strlen(ref_path_in);
- strcpy(abs_path_in, ref_path_in);
- for (int i = ref_path_in_len; i < FILE_MAX - 1; i++) {
- abs_path_in[i] = 'A';
- }
- abs_path_in[FILE_MAX - 1] = '\0';
- abs_path_out[0] = '/';
- abs_path_out[1] = '/';
- for (int i = 2; i < FILE_MAX - (int(ref_path_in_len) - 1); i++) {
- abs_path_out[i] = 'A';
- }
- abs_path_out[FILE_MAX - (ref_path_in_len - 1)] = '\0';
- PATH_REL(abs_path_in, ref_path_in, abs_path_out);
+TEST(path_util, PathRelPath_SimpleSubdir)
+{
+ PATH_REL(ABS_PREFIX "/foo/bar/blender.blend", ABS_PREFIX "/foo/bar", "//bar/blender.blend");
+}
+
+TEST(path_util, PathRelPath_BufferOverflowRoot)
+{
+ char abs_path_in[FILE_MAX];
+ const char *abs_prefix = ABS_PREFIX "/";
+ for (int i = STRNCPY_RLEN(abs_path_in, abs_prefix); i < FILE_MAX - 1; i++) {
+ abs_path_in[i] = 'A';
}
+ abs_path_in[FILE_MAX - 1] = '\0';
+ char abs_path_out[FILE_MAX];
+ for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - 1; i++) {
+ abs_path_out[i] = 'A';
+ }
+ abs_path_out[FILE_MAX - std::max((strlen(abs_prefix) - 1), size_t(1))] = '\0';
+ PATH_REL(abs_path_in, abs_prefix, abs_path_out);
}
-# undef PATH_REL
+TEST(path_util, PathRelPath_BufferOverflowSubdir)
+{
+ char abs_path_in[FILE_MAX];
+ const char *ref_path_in = ABS_PREFIX "/foo/bar/";
+ const size_t ref_path_in_len = strlen(ref_path_in);
+ for (int i = STRNCPY_RLEN(abs_path_in, ref_path_in); i < FILE_MAX - 1; i++) {
+ abs_path_in[i] = 'A';
+ }
+ abs_path_in[FILE_MAX - 1] = '\0';
+ char abs_path_out[FILE_MAX];
+ for (int i = STRNCPY_RLEN(abs_path_out, "//"); i < FILE_MAX - (int(ref_path_in_len) - 1); i++) {
+ abs_path_out[i] = 'A';
+ }
+ abs_path_out[FILE_MAX - std::max((ref_path_in_len - 1), size_t(1))] = '\0';
+ PATH_REL(abs_path_in, ref_path_in, abs_path_out);
+}
-#endif
+#undef PATH_REL
+#undef ABS_PREFIX
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Tests for: #BLI_path_contains
+ * \{ */
-/* BLI_path_contains */
TEST(path_util, PathContains)
{
EXPECT_TRUE(BLI_path_contains("/some/path", "/some/path")) << "A path contains itself";
@@ -692,4 +952,6 @@ TEST(path_util, PathContains_Windows_case_insensitive)
EXPECT_TRUE(BLI_path_contains("C:\\some\\path", "c:\\SOME\\path\\inside"))
<< "On Windows path comparison should ignore case";
}
-#endif
+#endif /* WIN32 */
+
+/** \} */