Cleanup: move BLI_str_replace into BLI_string_utils.h

String search & replace is a higher level function (unlike BLI_string.h)
which handlers lower level replacements for printing and string copying.

Also use BLI_string_* prefix (matching other utilities).

This makes it possible to use BLI_string in Blender's internal utilities
without depending on DynStr, MemArena... etc.
This commit is contained in:
Campbell Barton
2023-07-04 12:02:25 +10:00
parent bcdba3516b
commit 9753e70e37
23 changed files with 259 additions and 233 deletions

View File

@@ -25,6 +25,7 @@
#include "BLI_math_vector_types.hh" #include "BLI_math_vector_types.hh"
#include "BLI_polyfill_2d.h" #include "BLI_polyfill_2d.h"
#include "BLI_span.hh" #include "BLI_span.hh"
#include "BLI_string_utils.h"
#include "DNA_gpencil_legacy_types.h" #include "DNA_gpencil_legacy_types.h"
#include "DNA_gpencil_modifier_types.h" #include "DNA_gpencil_modifier_types.h"
@@ -2686,7 +2687,7 @@ static void make_element_name(const char *obname, const char *name, const int ma
SNPRINTF(str, "%s_%s", obname, name); SNPRINTF(str, "%s_%s", obname, name);
/* Replace any point by underscore. */ /* Replace any point by underscore. */
BLI_str_replace_char(str, '.', '_'); BLI_string_replace_char(str, '.', '_');
BLI_strncpy_utf8(r_name, str, maxlen); BLI_strncpy_utf8(r_name, str, maxlen);
} }

View File

@@ -22,6 +22,7 @@
#include <string> #include <string>
#include "BLI_array.hh" #include "BLI_array.hh"
#include "BLI_string_utils.h"
#include "CLG_log.h" #include "CLG_log.h"
@@ -3586,11 +3587,11 @@ char *BKE_image_get_tile_strformat(const char *filepath, eUDIM_TILE_FORMAT *r_ti
if (strstr(filepath, "<UDIM>") != nullptr) { if (strstr(filepath, "<UDIM>") != nullptr) {
*r_tile_format = UDIM_TILE_FORMAT_UDIM; *r_tile_format = UDIM_TILE_FORMAT_UDIM;
return BLI_str_replaceN(filepath, "<UDIM>", "%d"); return BLI_string_replaceN(filepath, "<UDIM>", "%d");
} }
if (strstr(filepath, "<UVTILE>") != nullptr) { if (strstr(filepath, "<UVTILE>") != nullptr) {
*r_tile_format = UDIM_TILE_FORMAT_UVTILE; *r_tile_format = UDIM_TILE_FORMAT_UVTILE;
return BLI_str_replaceN(filepath, "<UVTILE>", "u%d_v%d"); return BLI_string_replaceN(filepath, "<UVTILE>", "u%d_v%d");
} }
*r_tile_format = UDIM_TILE_FORMAT_NONE; *r_tile_format = UDIM_TILE_FORMAT_NONE;

View File

@@ -2503,7 +2503,7 @@ static void viewlayer_aov_make_name_unique(ViewLayer *view_layer)
/* Don't allow dots, it's incompatible with OpenEXR convention to store channels /* Don't allow dots, it's incompatible with OpenEXR convention to store channels
* as "layer.pass.channel". */ * as "layer.pass.channel". */
BLI_str_replace_char(aov->name, '.', '_'); BLI_string_replace_char(aov->name, '.', '_');
BLI_uniquename( BLI_uniquename(
&view_layer->aovs, aov, DATA_("AOV"), '_', offsetof(ViewLayerAOV, name), sizeof(aov->name)); &view_layer->aovs, aov, DATA_("AOV"), '_', offsetof(ViewLayerAOV, name), sizeof(aov->name));
} }
@@ -2620,7 +2620,7 @@ static void viewlayer_lightgroup_make_name_unique(ViewLayer *view_layer,
{ {
/* Don't allow dots, it's incompatible with OpenEXR convention to store channels /* Don't allow dots, it's incompatible with OpenEXR convention to store channels
* as "layer.pass.channel". */ * as "layer.pass.channel". */
BLI_str_replace_char(lightgroup->name, '.', '_'); BLI_string_replace_char(lightgroup->name, '.', '_');
BLI_uniquename(&view_layer->lightgroups, BLI_uniquename(&view_layer->lightgroups,
lightgroup, lightgroup,
DATA_("Lightgroup"), DATA_("Lightgroup"),

View File

@@ -15,6 +15,7 @@
#include "BLI_fileops.hh" #include "BLI_fileops.hh"
#include "BLI_hash_md5.h" #include "BLI_hash_md5.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_string_utils.h"
namespace blender::bke::sim { namespace blender::bke::sim {
@@ -78,7 +79,7 @@ void ModifierSimulationCache::try_discover_bake(const StringRefNull absolute_bak
} }
char modified_file_name[FILE_MAX]; char modified_file_name[FILE_MAX];
STRNCPY(modified_file_name, dir_entry.relname); STRNCPY(modified_file_name, dir_entry.relname);
BLI_str_replace_char(modified_file_name, '_', '.'); BLI_string_replace_char(modified_file_name, '_', '.');
const SubFrame frame = std::stof(modified_file_name); const SubFrame frame = std::stof(modified_file_name);

View File

@@ -541,7 +541,7 @@ void BKE_workspace_tool_id_replace_table(WorkSpace *workspace,
} }
idname_suffix += idname_prefix_len; idname_suffix += idname_prefix_len;
} }
BLI_str_replace_table_exact( BLI_string_replace_table_exact(
idname_suffix, idname_suffix_len, replace_table, replace_table_num); idname_suffix, idname_suffix_len, replace_table, replace_table_num);
} }
} }

View File

@@ -160,53 +160,6 @@ bool BLI_str_quoted_substr(const char *__restrict str,
const char *__restrict prefix, const char *__restrict prefix,
char *result, char *result,
size_t result_maxncpy); size_t result_maxncpy);
/**
* string with all instances of substr_old replaced with substr_new,
* Returns a copy of the c-string \a str into a newly #MEM_mallocN'd
* and returns it.
*
* \note A rather wasteful string-replacement utility, though this shall do for now.
* Feel free to replace this with an even safe + nicer alternative
*
* \param str: The string to replace occurrences of substr_old in
* \param substr_old: The text in the string to find and replace
* \param substr_new: The text in the string to find and replace
* \retval Returns the duplicated string
*/
char *BLI_str_replaceN(const char *__restrict str,
const char *__restrict substr_old,
const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2, 3) ATTR_MALLOC;
/**
* In-place replace every \a src to \a dst in \a str.
*
* \param str: The string to operate on.
* \param src: The character to replace.
* \param dst: The character to replace with.
*/
void BLI_str_replace_char(char *str, char src, char dst) ATTR_NONNULL(1);
/**
* Simple exact-match string replacement.
*
* \param replace_table: Array of source, destination pairs.
*
* \note Larger tables should use a hash table.
*/
bool BLI_str_replace_table_exact(char *string,
size_t string_len,
const char *replace_table[][2],
int replace_table_len);
/**
* Write `dst` into the range between `src_beg` & `src_end`,
* resize within `string_maxncpy` limits, ensure null terminated.
*
* \return the length of `string`.
*/
size_t BLI_str_replace_range(
char *string, size_t string_maxncpy, int src_beg, int src_end, const char *dst);
/** /**
* Portable replacement for #snprintf * Portable replacement for #snprintf

View File

@@ -21,6 +21,64 @@ struct ListBase;
typedef bool (*UniquenameCheckCallback)(void *arg, const char *name); typedef bool (*UniquenameCheckCallback)(void *arg, const char *name);
/* ------------------------------------------------------------------------- */
/** \name String Replace
* \{ */
/**
* string with all instances of substr_old replaced with substr_new,
* Returns a copy of the c-string \a str into a newly #MEM_mallocN'd
* and returns it.
*
* \note A rather wasteful string-replacement utility, though this shall do for now.
* Feel free to replace this with an even safe + nicer alternative
*
* \param str: The string to replace occurrences of substr_old in
* \param substr_old: The text in the string to find and replace
* \param substr_new: The text in the string to find and replace
* \retval Returns the duplicated string
*/
char *BLI_string_replaceN(const char *__restrict str,
const char *__restrict substr_old,
const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2, 3) ATTR_MALLOC;
/**
* In-place replace every \a src to \a dst in \a str.
*
* \param str: The string to operate on.
* \param src: The character to replace.
* \param dst: The character to replace with.
*/
void BLI_string_replace_char(char *str, char src, char dst) ATTR_NONNULL(1);
/**
* Simple exact-match string replacement.
*
* \param replace_table: Array of source, destination pairs.
*
* \note Larger tables should use a hash table.
*/
bool BLI_string_replace_table_exact(char *string,
size_t string_len,
const char *replace_table[][2],
int replace_table_len);
/**
* Write `dst` into the range between `src_beg` & `src_end`,
* resize within `string_maxncpy` limits, ensure null terminated.
*
* \return the length of `string`.
*/
size_t BLI_string_replace_range(
char *string, size_t string_maxncpy, int src_beg, int src_end, const char *dst);
/** \} */
/* ------------------------------------------------------------------------- */
/** \name String Split
* \{ */
/** /**
* Looks for a numeric suffix preceded by `delim` character on the end of * Looks for a numeric suffix preceded by `delim` character on the end of
* name, puts preceding part into *left and value of suffix into *nr. * name, puts preceding part into *left and value of suffix into *nr.
@@ -51,6 +109,8 @@ void BLI_string_split_suffix(const char *string, size_t string_maxlen, char *r_b
void BLI_string_split_prefix(const char *string, size_t string_maxlen, char *r_pre, char *r_body) void BLI_string_split_prefix(const char *string, size_t string_maxlen, char *r_pre, char *r_body)
ATTR_NONNULL(1, 3, 4); ATTR_NONNULL(1, 3, 4);
/** \} */
/** /**
* A version of #BLI_string_join_array_by_sep_charN that takes a table array. * 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. * The new location of each string is written into this array.

View File

@@ -18,6 +18,7 @@
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utf8.h" #include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#ifdef WIN32 #ifdef WIN32
@@ -723,8 +724,8 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
STRNCPY(temp, basepath); STRNCPY(temp, basepath);
#endif #endif
BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/'); BLI_string_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/');
BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/'); BLI_string_replace_char(path + BLI_path_unc_prefix_len(path), '\\', '/');
/* Remove `/./` which confuse the following slash counting. */ /* Remove `/./` which confuse the following slash counting. */
BLI_path_normalize(path); BLI_path_normalize(path);
@@ -790,7 +791,7 @@ void BLI_path_rel(char path[FILE_MAX], const char *basepath)
r += BLI_strncpy_rlen(r, q + 1, sizeof(res) - (r - res)); r += BLI_strncpy_rlen(r, q + 1, sizeof(res) - (r - res));
#ifdef WIN32 #ifdef WIN32
BLI_str_replace_char(res + 2, '/', '\\'); BLI_string_replace_char(res + 2, '/', '\\');
#endif #endif
BLI_strncpy(path, res, FILE_MAX); BLI_strncpy(path, res, FILE_MAX);
} }
@@ -964,7 +965,7 @@ bool BLI_path_frame(char *path, size_t path_maxncpy, int frame, int digits)
char frame_str[FILENAME_FRAME_CHARS_MAX + 1]; /* One for null. */ char frame_str[FILENAME_FRAME_CHARS_MAX + 1]; /* One for null. */
const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX);
SNPRINTF(frame_str, "%.*d", ch_span, frame); SNPRINTF(frame_str, "%.*d", ch_span, frame);
BLI_str_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str); BLI_string_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str);
return true; return true;
} }
return false; return false;
@@ -984,7 +985,7 @@ bool BLI_path_frame_range(char *path, size_t path_maxncpy, int sta, int end, int
char frame_str[(FILENAME_FRAME_CHARS_MAX * 2) + 1 + 1]; /* One for null, one for the '-' */ char frame_str[(FILENAME_FRAME_CHARS_MAX * 2) + 1 + 1]; /* One for null, one for the '-' */
const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX); const int ch_span = MIN2(ch_end - ch_sta, FILENAME_FRAME_CHARS_MAX);
SNPRINTF(frame_str, "%.*d-%.*d", ch_span, sta, ch_span, end); SNPRINTF(frame_str, "%.*d-%.*d", ch_span, sta, ch_span, end);
BLI_str_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str); BLI_string_replace_range(path, path_maxncpy, ch_sta, ch_end, frame_str);
return true; return true;
} }
return false; return false;
@@ -1066,7 +1067,7 @@ void BLI_path_to_display_name(char *display_name, int display_name_maxncpy, cons
BLI_strncpy(display_name, name + strip_offset, display_name_maxncpy); BLI_strncpy(display_name, name + strip_offset, display_name_maxncpy);
/* Replace underscores with spaces. */ /* Replace underscores with spaces. */
BLI_str_replace_char(display_name, '_', ' '); BLI_string_replace_char(display_name, '_', ' ');
BLI_path_extension_strip(display_name); BLI_path_extension_strip(display_name);
@@ -1150,7 +1151,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
* NOTE(@elubie): For UNC paths the first characters containing the UNC prefix * NOTE(@elubie): For UNC paths the first characters containing the UNC prefix
* shouldn't be switched as we need to distinguish them from * shouldn't be switched as we need to distinguish them from
* paths relative to the `.blend` file. */ * paths relative to the `.blend` file. */
BLI_str_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/'); BLI_string_replace_char(tmp + BLI_path_unc_prefix_len(tmp), '\\', '/');
/* Paths starting with `//` will get the blend file as their base, /* Paths starting with `//` will get the blend file as their base,
* this isn't standard in any OS but is used in blender all over the place. */ * this isn't standard in any OS but is used in blender all over the place. */
@@ -1161,7 +1162,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
/* File component is ignored, so don't bother with the trailing slash. */ /* File component is ignored, so don't bother with the trailing slash. */
BLI_path_normalize(base); BLI_path_normalize(base);
lslash = BLI_path_slash_rfind(base); lslash = BLI_path_slash_rfind(base);
BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/'); BLI_string_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/');
if (lslash) { if (lslash) {
/* Length up to and including last `/`. */ /* Length up to and including last `/`. */
@@ -1187,7 +1188,7 @@ bool BLI_path_abs(char path[FILE_MAX], const char *basepath)
/* NOTE(@jesterking): Skip first two chars, which in case of absolute path will /* NOTE(@jesterking): Skip first two chars, which in case of absolute path will
* be `drive:/blabla` and in case of `relpath` `//blabla/`. * be `drive:/blabla` and in case of `relpath` `//blabla/`.
* So `relpath` `//` will be retained, rest will be nice and shiny WIN32 backward slashes. */ * So `relpath` `//` will be retained, rest will be nice and shiny WIN32 backward slashes. */
BLI_str_replace_char(path + 2, '/', '\\'); BLI_string_replace_char(path + 2, '/', '\\');
#endif #endif
/* Ensure this is after correcting for path switch. */ /* Ensure this is after correcting for path switch. */
@@ -1968,10 +1969,10 @@ void BLI_path_slash_native(char *path)
{ {
#ifdef WIN32 #ifdef WIN32
if (path && BLI_strnlen(path, 3) > 2) { if (path && BLI_strnlen(path, 3) > 2) {
BLI_str_replace_char(path + 2, ALTSEP, SEP); BLI_string_replace_char(path + 2, ALTSEP, SEP);
} }
#else #else
BLI_str_replace_char(path + BLI_path_unc_prefix_len(path), ALTSEP, SEP); BLI_string_replace_char(path + BLI_path_unc_prefix_len(path), ALTSEP, SEP);
#endif #endif
} }

View File

@@ -16,7 +16,6 @@
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "BLI_dynstr.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
@@ -528,142 +527,6 @@ bool BLI_str_quoted_substr(const char *__restrict str,
/** \} */ /** \} */
/* -------------------------------------------------------------------- */
/** \name String Replace
* \{ */
char *BLI_str_replaceN(const char *__restrict str,
const char *__restrict substr_old,
const char *__restrict substr_new)
{
DynStr *ds = NULL;
size_t len_old = strlen(substr_old);
const char *match;
BLI_assert(substr_old[0] != '\0');
/* While we can still find a match for the old sub-string that we're searching for,
* keep dicing and replacing. */
while ((match = strstr(str, substr_old))) {
/* the assembly buffer only gets created when we actually need to rebuild the string */
if (ds == NULL) {
ds = BLI_dynstr_new();
}
/* If the match position does not match the current position in the string,
* copy the text up to this position and advance the current position in the string. */
if (str != match) {
/* Add the segment of the string from `str` to match to the buffer,
* then restore the value at match. */
BLI_dynstr_nappend(ds, str, (match - str));
/* now our current position should be set on the start of the match */
str = match;
}
/* Add the replacement text to the accumulation buffer. */
BLI_dynstr_append(ds, substr_new);
/* Advance the current position of the string up to the end of the replaced segment. */
str += len_old;
}
/* Finish off and return a new string that has had all occurrences of. */
if (ds) {
char *str_new;
/* Add what's left of the string to the assembly buffer
* - we've been adjusting `str` to point at the end of the replaced segments. */
BLI_dynstr_append(ds, str);
/* Convert to new c-string (MEM_malloc'd), and free the buffer. */
str_new = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return str_new;
}
/* Just create a new copy of the entire string - we avoid going through the assembly buffer
* for what should be a bit more efficiency. */
return BLI_strdup(str);
}
void BLI_str_replace_char(char *str, char src, char dst)
{
while (*str) {
if (*str == src) {
*str = dst;
}
str++;
}
}
bool BLI_str_replace_table_exact(char *string,
const size_t string_maxncpy,
const char *replace_table[][2],
int replace_table_len)
{
BLI_string_debug_size_after_nil(string, string_maxncpy);
for (int i = 0; i < replace_table_len; i++) {
if (STREQ(string, replace_table[i][0])) {
BLI_strncpy(string, replace_table[i][1], string_maxncpy);
return true;
}
}
return false;
}
size_t BLI_str_replace_range(
char *string, size_t string_maxncpy, int src_beg, int src_end, const char *dst)
{
int string_len = strlen(string);
BLI_assert(src_beg <= src_end);
BLI_assert(src_end <= string_len);
const int src_len = src_end - src_beg;
int dst_len = strlen(dst);
if (src_len < dst_len) {
/* Grow, first handle special cases. */
/* Special case, the src_end is entirely clipped. */
if (UNLIKELY(string_maxncpy <= src_beg + dst_len)) {
/* There is only room for the destination. */
dst_len = ((int)string_maxncpy - src_beg) - 1;
string_len = src_end;
string[string_len] = '\0';
}
const int ofs = dst_len - src_len;
/* Clip the string when inserting the destination string exceeds `string_maxncpy`. */
if (string_len + ofs >= string_maxncpy) {
string_len = ((int)string_maxncpy - ofs) - 1;
string[string_len] = '\0';
BLI_assert(src_end <= string_len);
}
/* Grow. */
memmove(string + (src_end + ofs), string + src_end, (size_t)(string_len - src_end) + 1);
string_len += ofs;
}
else if (src_len > dst_len) {
/* Shrink. */
const int ofs = src_len - dst_len;
memmove(string + (src_end - ofs), string + src_end, (size_t)(string_len - src_end) + 1);
string_len -= ofs;
}
else { /* Simple case, no resizing. */
BLI_assert(src_len == dst_len);
}
if (dst_len > 0) {
memcpy(string + src_beg, dst, (size_t)dst_len);
}
BLI_assert(string[string_len] == '\0');
return (size_t)string_len;
}
/** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name String Comparison/Matching /** \name String Comparison/Matching
* \{ */ * \{ */

View File

@@ -17,12 +17,150 @@
#include "BLI_string_utils.h" #include "BLI_string_utils.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLI_dynstr.h"
#include "DNA_listBase.h" #include "DNA_listBase.h"
#ifdef __GNUC__ #ifdef __GNUC__
# pragma GCC diagnostic error "-Wsign-conversion" # pragma GCC diagnostic error "-Wsign-conversion"
#endif #endif
/* -------------------------------------------------------------------- */
/** \name String Replace
* \{ */
char *BLI_string_replaceN(const char *__restrict str,
const char *__restrict substr_old,
const char *__restrict substr_new)
{
DynStr *ds = NULL;
size_t len_old = strlen(substr_old);
const char *match;
BLI_assert(substr_old[0] != '\0');
/* While we can still find a match for the old sub-string that we're searching for,
* keep dicing and replacing. */
while ((match = strstr(str, substr_old))) {
/* the assembly buffer only gets created when we actually need to rebuild the string */
if (ds == NULL) {
ds = BLI_dynstr_new();
}
/* If the match position does not match the current position in the string,
* copy the text up to this position and advance the current position in the string. */
if (str != match) {
/* Add the segment of the string from `str` to match to the buffer,
* then restore the value at match. */
BLI_dynstr_nappend(ds, str, (match - str));
/* now our current position should be set on the start of the match */
str = match;
}
/* Add the replacement text to the accumulation buffer. */
BLI_dynstr_append(ds, substr_new);
/* Advance the current position of the string up to the end of the replaced segment. */
str += len_old;
}
/* Finish off and return a new string that has had all occurrences of. */
if (ds) {
char *str_new;
/* Add what's left of the string to the assembly buffer
* - we've been adjusting `str` to point at the end of the replaced segments. */
BLI_dynstr_append(ds, str);
/* Convert to new c-string (MEM_malloc'd), and free the buffer. */
str_new = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
return str_new;
}
/* Just create a new copy of the entire string - we avoid going through the assembly buffer
* for what should be a bit more efficiency. */
return BLI_strdup(str);
}
void BLI_string_replace_char(char *str, char src, char dst)
{
while (*str) {
if (*str == src) {
*str = dst;
}
str++;
}
}
bool BLI_string_replace_table_exact(char *string,
const size_t string_maxncpy,
const char *replace_table[][2],
int replace_table_len)
{
BLI_string_debug_size_after_nil(string, string_maxncpy);
for (int i = 0; i < replace_table_len; i++) {
if (STREQ(string, replace_table[i][0])) {
BLI_strncpy(string, replace_table[i][1], string_maxncpy);
return true;
}
}
return false;
}
size_t BLI_string_replace_range(
char *string, size_t string_maxncpy, int src_beg, int src_end, const char *dst)
{
int string_len = strlen(string);
BLI_assert(src_beg <= src_end);
BLI_assert(src_end <= string_len);
const int src_len = src_end - src_beg;
int dst_len = strlen(dst);
if (src_len < dst_len) {
/* Grow, first handle special cases. */
/* Special case, the src_end is entirely clipped. */
if (UNLIKELY(string_maxncpy <= src_beg + dst_len)) {
/* There is only room for the destination. */
dst_len = ((int)string_maxncpy - src_beg) - 1;
string_len = src_end;
string[string_len] = '\0';
}
const int ofs = dst_len - src_len;
/* Clip the string when inserting the destination string exceeds `string_maxncpy`. */
if (string_len + ofs >= string_maxncpy) {
string_len = ((int)string_maxncpy - ofs) - 1;
string[string_len] = '\0';
BLI_assert(src_end <= string_len);
}
/* Grow. */
memmove(string + (src_end + ofs), string + src_end, (size_t)(string_len - src_end) + 1);
string_len += ofs;
}
else if (src_len > dst_len) {
/* Shrink. */
const int ofs = src_len - dst_len;
memmove(string + (src_end - ofs), string + src_end, (size_t)(string_len - src_end) + 1);
string_len -= ofs;
}
else { /* Simple case, no resizing. */
BLI_assert(src_len == dst_len);
}
if (dst_len > 0) {
memcpy(string + src_beg, dst, (size_t)dst_len);
}
BLI_assert(string[string_len] == '\0');
return (size_t)string_len;
}
/** \} */
size_t BLI_string_split_name_number(const char *name, size_t BLI_string_split_name_number(const char *name,
const char delim, const char delim,
char *r_name_left, char *r_name_left,

View File

@@ -8,6 +8,7 @@
#include "BLI_array_utils.h" #include "BLI_array_utils.h"
#include "BLI_memiter.h" #include "BLI_memiter.h"
#include "BLI_string_utils.h"
#include "BLI_ressource_strings.h" #include "BLI_ressource_strings.h"
#include "BLI_string.h" #include "BLI_string.h"
@@ -100,7 +101,7 @@ static void memiter_words10k_test(const char split_char, const int chunk_size)
{ {
const int words_len = sizeof(words10k) - 1; const int words_len = sizeof(words10k) - 1;
char *words = BLI_strdupn(words10k, words_len); char *words = BLI_strdupn(words10k, words_len);
BLI_str_replace_char(words, split_char, '\0'); BLI_string_replace_char(words, split_char, '\0');
BLI_memiter *mi = BLI_memiter_create(chunk_size); BLI_memiter *mi = BLI_memiter_create(chunk_size);

View File

@@ -9,6 +9,7 @@
#include "BLI_fileops.h" #include "BLI_fileops.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utils.h"
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Local Utilities /** \name Local Utilities
@@ -25,7 +26,7 @@ static void str_replace_char_with_relative_exception(char *str, char src, char d
} }
} }
} }
BLI_str_replace_char(str, src, dst); BLI_string_replace_char(str, src, dst);
} }
static char *str_replace_char_strdup(const char *str, char src, char dst) static char *str_replace_char_strdup(const char *str, char src, char dst)
@@ -34,7 +35,7 @@ static char *str_replace_char_strdup(const char *str, char src, char dst)
return nullptr; return nullptr;
} }
char *str_dupe = strdup(str); char *str_dupe = strdup(str);
BLI_str_replace_char(str_dupe, src, dst); BLI_string_replace_char(str_dupe, src, dst);
return str_dupe; return str_dupe;
} }
@@ -52,7 +53,7 @@ static char *str_replace_char_strdup(const char *str, char src, char dst)
} \ } \
const int path_len_test = BLI_path_normalize(path); \ const int path_len_test = BLI_path_normalize(path); \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '\\', '/'); \ BLI_string_replace_char(path, '\\', '/'); \
} \ } \
EXPECT_STREQ(path, output_expect); \ EXPECT_STREQ(path, output_expect); \
EXPECT_EQ(path_len_test, strlen(path)); \ EXPECT_EQ(path_len_test, strlen(path)); \
@@ -190,11 +191,11 @@ TEST(path_util, CompareNormalized)
{ \ { \
char path[FILE_MAX] = input; \ char path[FILE_MAX] = input; \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '/', '\\'); \ BLI_string_replace_char(path, '/', '\\'); \
} \ } \
BLI_path_parent_dir(path); \ BLI_path_parent_dir(path); \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '\\', '/'); \ BLI_string_replace_char(path, '\\', '/'); \
} \ } \
EXPECT_STREQ(path, output_expect); \ EXPECT_STREQ(path, output_expect); \
} \ } \
@@ -251,7 +252,7 @@ TEST(path_util, ParentDir_Complex)
char path[] = str_input; \ char path[] = str_input; \
/* Test input assumes forward slash, support back-slash on WIN32. */ \ /* Test input assumes forward slash, support back-slash on WIN32. */ \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '/', '\\'); \ BLI_string_replace_char(path, '/', '\\'); \
} \ } \
const char *expect = str_expect; \ const char *expect = str_expect; \
int index_output, len_output; \ int index_output, len_output; \
@@ -469,7 +470,7 @@ TEST(path_util, NameAtIndex_NoneComplexNeg)
char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \ char *input_back_slash[ARRAY_SIZE(input_forward_slash)] = {nullptr}; \
for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
input_back_slash[i] = strdup(input_forward_slash[i]); \ input_back_slash[i] = strdup(input_forward_slash[i]); \
BLI_str_replace_char(input_back_slash[i], '/', '\\'); \ BLI_string_replace_char(input_back_slash[i], '/', '\\'); \
} \ } \
/* Check we don't write past the last byte. */ \ /* Check we don't write past the last byte. */ \
result[out_size] = '\0'; \ result[out_size] = '\0'; \
@@ -477,7 +478,7 @@ TEST(path_util, NameAtIndex_NoneComplexNeg)
out_size, \ out_size, \
const_cast<const char **>(input_back_slash), \ const_cast<const char **>(input_back_slash), \
ARRAY_SIZE(input_back_slash)); \ ARRAY_SIZE(input_back_slash)); \
BLI_str_replace_char(result, '\\', '/'); \ BLI_string_replace_char(result, '\\', '/'); \
EXPECT_STREQ(result, expect); \ EXPECT_STREQ(result, expect); \
EXPECT_EQ(result[out_size], '\0'); \ EXPECT_EQ(result[out_size], '\0'); \
for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \ for (int i = 0; i < ARRAY_SIZE(input_forward_slash); i++) { \
@@ -599,12 +600,12 @@ TEST(path_util, JoinRelativePrefix)
char filename_native[] = filename; \ char filename_native[] = filename; \
/* Check we don't write past the last byte. */ \ /* Check we don't write past the last byte. */ \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(filename_native, '/', '\\'); \ BLI_string_replace_char(filename_native, '/', '\\'); \
BLI_str_replace_char(result, '/', '\\'); \ BLI_string_replace_char(result, '/', '\\'); \
} \ } \
BLI_path_append(result, size, filename_native); \ BLI_path_append(result, size, filename_native); \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(result, '\\', '/'); \ BLI_string_replace_char(result, '\\', '/'); \
} \ } \
EXPECT_STREQ(result, expect); \ EXPECT_STREQ(result, expect); \
} \ } \
@@ -1215,12 +1216,12 @@ TEST(path_util, Suffix)
const char *ref_path_test = ref_path; \ const char *ref_path_test = ref_path; \
STRNCPY(path, abs_path); \ STRNCPY(path, abs_path); \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '/', '\\'); \ BLI_string_replace_char(path, '/', '\\'); \
ref_path_test = str_replace_char_strdup(ref_path_test, '/', '\\'); \ ref_path_test = str_replace_char_strdup(ref_path_test, '/', '\\'); \
} \ } \
BLI_path_rel(path, ref_path_test); \ BLI_path_rel(path, ref_path_test); \
if (SEP == '\\') { \ if (SEP == '\\') { \
BLI_str_replace_char(path, '\\', '/'); \ BLI_string_replace_char(path, '\\', '/'); \
free((void *)ref_path_test); \ free((void *)ref_path_test); \
} \ } \
EXPECT_STREQ(path, rel_path_expect); \ EXPECT_STREQ(path, rel_path_expect); \

View File

@@ -162,7 +162,7 @@ TEST(string, StrReplaceRange)
#define STR_REPLACE_RANGE(src, size, beg, end, dst, result_expect) \ #define STR_REPLACE_RANGE(src, size, beg, end, dst, result_expect) \
{ \ { \
char string[size] = src; \ char string[size] = src; \
BLI_str_replace_range(string, sizeof(string), beg, end, dst); \ BLI_string_replace_range(string, sizeof(string), beg, end, dst); \
EXPECT_STREQ(string, result_expect); \ EXPECT_STREQ(string, result_expect); \
} }

View File

@@ -364,10 +364,10 @@ static char *replace_bbone_easing_rnapath(char *old_path)
* which happen be named after the bbone property id's * which happen be named after the bbone property id's
*/ */
if (strstr(old_path, "bbone_in")) { if (strstr(old_path, "bbone_in")) {
new_path = BLI_str_replaceN(old_path, "bbone_in", "bbone_easein"); new_path = BLI_string_replaceN(old_path, "bbone_in", "bbone_easein");
} }
else if (strstr(old_path, "bbone_out")) { else if (strstr(old_path, "bbone_out")) {
new_path = BLI_str_replaceN(old_path, "bbone_out", "bbone_easeout"); new_path = BLI_string_replaceN(old_path, "bbone_out", "bbone_easeout");
} }
if (new_path) { if (new_path) {

View File

@@ -462,7 +462,7 @@ static void do_versions_sequencer_speed_effect_recursive(Scene *scene, const Lis
} }
} }
if (substr) { if (substr) {
char *new_path = BLI_str_replaceN(fcu->rna_path, "speed_factor", substr); char *new_path = BLI_string_replaceN(fcu->rna_path, "speed_factor", substr);
MEM_freeN(fcu->rna_path); MEM_freeN(fcu->rna_path);
fcu->rna_path = new_path; fcu->rna_path = new_path;
} }

View File

@@ -14,6 +14,7 @@
#include "BLI_math.h" #include "BLI_math.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utf8.h" #include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "DNA_anim_types.h" #include "DNA_anim_types.h"
@@ -708,10 +709,10 @@ void blo_do_versions_userdef(UserDef *userdef)
}; };
const int replace_table_len = ARRAY_SIZE(replace_table); const int replace_table_len = ARRAY_SIZE(replace_table);
BLI_str_replace_table_exact( BLI_string_replace_table_exact(
userdef->keyconfigstr, sizeof(userdef->keyconfigstr), replace_table, replace_table_len); userdef->keyconfigstr, sizeof(userdef->keyconfigstr), replace_table, replace_table_len);
LISTBASE_FOREACH (wmKeyConfigPref *, kpt, &userdef->user_keyconfig_prefs) { LISTBASE_FOREACH (wmKeyConfigPref *, kpt, &userdef->user_keyconfig_prefs) {
BLI_str_replace_table_exact( BLI_string_replace_table_exact(
kpt->idname, sizeof(kpt->idname), replace_table, replace_table_len); kpt->idname, sizeof(kpt->idname), replace_table, replace_table_len);
} }
} }

View File

@@ -504,7 +504,7 @@ static void updateDuplicateActionConstraintSettings(
char *old_path = new_curve->rna_path; char *old_path = new_curve->rna_path;
new_curve->rna_path = BLI_str_replaceN(old_path, orig_bone->name, dup_bone->name); new_curve->rna_path = BLI_string_replaceN(old_path, orig_bone->name, dup_bone->name);
MEM_freeN(old_path); MEM_freeN(old_path);
/* Flip the animation */ /* Flip the animation */

View File

@@ -11,6 +11,7 @@
#include "BLI_fileops.hh" #include "BLI_fileops.hh"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_serialize.hh" #include "BLI_serialize.hh"
#include "BLI_string_utils.h"
#include "BLI_vector.hh" #include "BLI_vector.hh"
#include "PIL_time.h" #include "PIL_time.h"
@@ -286,7 +287,7 @@ static void bake_simulation_job_startjob(void *customdata,
char frame_file_c_str[64]; char frame_file_c_str[64];
SNPRINTF(frame_file_c_str, "%011.5f", double(frame)); SNPRINTF(frame_file_c_str, "%011.5f", double(frame));
BLI_str_replace_char(frame_file_c_str, '.', '_'); BLI_string_replace_char(frame_file_c_str, '.', '_');
const StringRefNull frame_file_str = frame_file_c_str; const StringRefNull frame_file_str = frame_file_c_str;
BKE_scene_graph_update_for_newframe(job.depsgraph); BKE_scene_graph_update_for_newframe(job.depsgraph);

View File

@@ -26,6 +26,7 @@
#include "BLI_listbase.h" #include "BLI_listbase.h"
#include "BLI_math_vector.h" #include "BLI_math_vector.h"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
#include "BLT_translation.h" #include "BLT_translation.h"
@@ -1144,7 +1145,7 @@ static int view_layer_add_lightgroup_exec(bContext *C, wmOperator *op)
if (RNA_struct_property_is_set(op->ptr, "name")) { if (RNA_struct_property_is_set(op->ptr, "name")) {
RNA_string_get(op->ptr, "name", name); RNA_string_get(op->ptr, "name", name);
/* Ensure that there are no dots in the name. */ /* Ensure that there are no dots in the name. */
BLI_str_replace_char(name, '.', '_'); BLI_string_replace_char(name, '.', '_');
LISTBASE_FOREACH (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) { LISTBASE_FOREACH (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) {
if (STREQ(lightgroup->name, name)) { if (STREQ(lightgroup->name, name)) {
return OPERATOR_CANCELLED; return OPERATOR_CANCELLED;

View File

@@ -13,6 +13,7 @@
#include "BLI_dynstr.h" #include "BLI_dynstr.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utils.h"
#include "GPU_platform.h" #include "GPU_platform.h"
@@ -45,8 +46,8 @@ static char *create_key(eGPUSupportLevel support_level,
char *support_key = BLI_dynstr_get_cstring(ds); char *support_key = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds); BLI_dynstr_free(ds);
BLI_str_replace_char(support_key, '\n', ' '); BLI_string_replace_char(support_key, '\n', ' ');
BLI_str_replace_char(support_key, '\r', ' '); BLI_string_replace_char(support_key, '\r', ' ');
return support_key; return support_key;
} }
@@ -57,8 +58,8 @@ static char *create_gpu_name(const char *vendor, const char *renderer, const cha
char *gpu_name = BLI_dynstr_get_cstring(ds); char *gpu_name = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds); BLI_dynstr_free(ds);
BLI_str_replace_char(gpu_name, '\n', ' '); BLI_string_replace_char(gpu_name, '\n', ' ');
BLI_str_replace_char(gpu_name, '\r', ' '); BLI_string_replace_char(gpu_name, '\r', ' ');
return gpu_name; return gpu_name;
} }

View File

@@ -241,7 +241,7 @@ static bool uri_from_filename(const char *path, char *uri)
/* Not a correct absolute path with a drive letter or UNC prefix. */ /* Not a correct absolute path with a drive letter or UNC prefix. */
return false; return false;
} }
BLI_str_replace_char(orig_uri, '\\', '/'); BLI_string_replace_char(orig_uri, '\\', '/');
#else #else
SNPRINTF(orig_uri, "file://%s", path); SNPRINTF(orig_uri, "file://%s", path);
#endif #endif

View File

@@ -22,6 +22,7 @@
#include "BLI_memory_utils.hh" #include "BLI_memory_utils.hh"
#include "BLI_path_util.h" #include "BLI_path_util.h"
#include "BLI_string.h" #include "BLI_string.h"
#include "BLI_string_utils.h"
#include "DNA_material_types.h" #include "DNA_material_types.h"
@@ -659,7 +660,7 @@ static std::string get_tex_image_asset_filepath(bNode *node,
BLI_path_split_dir_part(stage_path.c_str(), dir_path, FILE_MAX); BLI_path_split_dir_part(stage_path.c_str(), dir_path, FILE_MAX);
BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path); BLI_path_join(exp_path, FILE_MAX, dir_path, "textures", file_path);
} }
BLI_str_replace_char(exp_path, '\\', '/'); BLI_string_replace_char(exp_path, '\\', '/');
return exp_path; return exp_path;
} }
@@ -678,7 +679,7 @@ static std::string get_tex_image_asset_filepath(bNode *node,
if (!BLI_path_is_rel(rel_path)) { if (!BLI_path_is_rel(rel_path)) {
return path; return path;
} }
BLI_str_replace_char(rel_path, '\\', '/'); BLI_string_replace_char(rel_path, '\\', '/');
return rel_path + 2; return rel_path + 2;
} }

View File

@@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */ * SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string_utf8.h" #include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "node_function_util.hh" #include "node_function_util.hh"
@@ -23,7 +24,7 @@ static std::string replace_all(const StringRefNull str,
if (from.is_empty()) { if (from.is_empty()) {
return str; return str;
} }
char *new_str_ptr = BLI_str_replaceN(str.c_str(), from.c_str(), to.c_str()); char *new_str_ptr = BLI_string_replaceN(str.c_str(), from.c_str(), to.c_str());
std::string new_str{new_str_ptr}; std::string new_str{new_str_ptr};
MEM_freeN(new_str_ptr); MEM_freeN(new_str_ptr);
return new_str; return new_str;