2024-06-04 20:53:57 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
|
|
|
|
|
|
#include "usd_utils.hh"
|
|
|
|
|
|
2025-02-21 20:17:42 +01:00
|
|
|
#include "BLI_array.hh"
|
|
|
|
|
#include "BLI_string_ref.hh"
|
2024-06-04 20:53:57 +02:00
|
|
|
#include "BLI_string_utf8.h"
|
|
|
|
|
|
|
|
|
|
#include <pxr/base/tf/stringUtils.h>
|
2025-02-27 00:15:41 +01:00
|
|
|
#include <pxr/base/tf/unicodeUtils.h>
|
2024-06-04 20:53:57 +02:00
|
|
|
|
|
|
|
|
namespace blender::io::usd {
|
|
|
|
|
|
2025-02-27 00:15:41 +01:00
|
|
|
std::string make_safe_name(const StringRef name, bool allow_unicode)
|
2024-06-04 20:53:57 +02:00
|
|
|
{
|
2025-02-21 20:17:42 +01:00
|
|
|
if (name.is_empty()) {
|
2024-06-04 20:53:57 +02:00
|
|
|
return "_";
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-21 20:17:42 +01:00
|
|
|
/* Create temporary buffer with exact amount of space required. */
|
|
|
|
|
const bool has_leading_digit = std::isdigit(name[0]);
|
|
|
|
|
Array<char, 64> storage(name.size() + (has_leading_digit ? 1 : 0));
|
|
|
|
|
MutableSpan<char> buf(storage);
|
2024-06-04 20:53:57 +02:00
|
|
|
|
2025-02-21 20:17:42 +01:00
|
|
|
/* Insert a leading '_' to account for names starting with digits. */
|
2024-06-04 20:53:57 +02:00
|
|
|
size_t offset = 0;
|
2025-02-21 20:17:42 +01:00
|
|
|
bool first = true;
|
|
|
|
|
if (has_leading_digit) {
|
|
|
|
|
buf[0] = '_';
|
|
|
|
|
offset = 1;
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!allow_unicode) {
|
|
|
|
|
buf.take_back(name.size()).copy_from(name);
|
|
|
|
|
offset += name.size();
|
|
|
|
|
return pxr::TfMakeValidIdentifier({buf.data(), offset});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-04 20:53:57 +02:00
|
|
|
for (auto cp : pxr::TfUtf8CodePointView{name}) {
|
|
|
|
|
constexpr pxr::TfUtf8CodePoint cp_underscore = pxr::TfUtf8CodePointFromAscii('_');
|
|
|
|
|
const bool cp_allowed = first ? (cp == cp_underscore || pxr::TfIsUtf8CodePointXidStart(cp)) :
|
|
|
|
|
pxr::TfIsUtf8CodePointXidContinue(cp);
|
|
|
|
|
if (!cp_allowed) {
|
|
|
|
|
offset += BLI_str_utf8_from_unicode(uint32_t('_'), buf.data() + offset, buf.size() - offset);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
offset += BLI_str_utf8_from_unicode(cp.AsUInt32(), buf.data() + offset, buf.size() - offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
first = false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-21 20:17:42 +01:00
|
|
|
return {buf.data(), offset};
|
2024-06-04 20:53:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::io::usd
|