Refactor: BLI: Re-implement BLI_string_split_name_number in C++.

Allows to use this code from C++ code/data, without duplicating strings
to char arrays. C-compatible API is kept as a wrapper around the new
implementation.

No behavioral change is expected from this commit.

Part of !135199.
This commit is contained in:
Bastien Montagne
2025-02-28 17:08:31 +01:00
parent b0d63ff8e1
commit 00f406c34c
2 changed files with 38 additions and 26 deletions

View File

@@ -94,6 +94,9 @@ size_t BLI_string_replace_range(
*/
size_t BLI_string_split_name_number(const char *name, char delim, char *r_name_left, int *r_number)
ATTR_NONNULL(1, 3, 4);
blender::StringRef BLI_string_split_name_number(const blender::StringRef name_full,
char delim,
int &r_number);
bool BLI_string_is_decimal(const char *string) ATTR_NONNULL(1);
/**

View File

@@ -12,6 +12,8 @@
#include <array>
#include <stdexcept>
#include "MEM_guardedalloc.h"
#include "BLI_array.hh"
@@ -162,37 +164,44 @@ size_t BLI_string_replace_range(
/** \} */
blender::StringRef BLI_string_split_name_number(const blender::StringRef name_full,
const char delim,
int &r_number)
{
const int64_t delim_index = name_full.rfind(delim);
r_number = 0;
if (delim_index == blender::StringRef::not_found) {
return name_full;
}
blender::StringRef name_base = name_full.substr(0, delim_index);
if (delim_index < name_full.size() - 1) {
const blender::StringRef num_str = name_full.substr(delim_index + 1);
if (!std::all_of(num_str.begin(), num_str.end(), ::isdigit)) {
return name_full;
}
/* Converting numerical suffix to an int, can overflow for large numbers. */
try {
r_number = std::stoi(num_str);
return name_base;
}
catch (std::out_of_range const & /*ex*/) {
r_number = 0;
}
}
return name_full;
}
size_t BLI_string_split_name_number(const char *name,
const char delim,
char *r_name_left,
int *r_number)
{
const size_t name_len = strlen(name);
*r_number = 0;
memcpy(r_name_left, name, (name_len + 1) * sizeof(char));
/* name doesn't end with a delimiter "foo." */
if ((name_len > 1 && name[name_len - 1] == delim) == 0) {
size_t a = name_len;
while (a--) {
if (name[a] == delim) {
r_name_left[a] = '\0'; /* truncate left part here */
*r_number = int(atol(name + a + 1));
/* casting down to an int, can overflow for large numbers */
if (*r_number < 0) {
*r_number = 0;
}
return a;
}
if (isdigit(name[a]) == 0) {
/* non-numeric suffix - give up */
break;
}
}
}
return name_len;
const std::string name_base = BLI_string_split_name_number(name, delim, *r_number);
BLI_strncpy(r_name_left, name_base.c_str(), name_base.size() + 1);
return name_base.size();
}
bool BLI_string_is_decimal(const char *string)