Files
test/source/blender/blenkernel/BKE_main_namemap.hh
Bastien Montagne 16e552298c Refactor: Core: ID's 'namemap' used to generate unique ID names.
Note: This commit is essentially non-behavioral change, expect in some
fairly rare edge cases.

This commit does a few things:
* Move the whole BKE_main_namemap code to modern C++.
* Split API calls to work with the global namemap, or the local ones.
* Simplify and make the code easier to follow and understand.
* Reduce 'default' memory usage by using growing BitVector for numeric
  suffix management, instead of a fixed 1K items.
* Fix inconsistent handling of 'same base name and numeric suffix,
  different name' issues (e.g. 'Foo.1' and 'Foo.001'), see
  `re_create_equivalent_numeric_suffixes` new unittest.
* Fix completely broken handling of `global` namemaps. This was
  (probably!) OK so far because of their currently very limited
  use-cases.

It also adds a few minor improvements to existing behavior (essentially
in exotic rare edge cases):
* Names that get too long are now only shortened by one char at a time,
  trying to modify the requested base name as little as possible.
* Names that are short, but for which all the manageable numeric suffixes
  are already in use, are extended with an (increasing)  number, instead
  of being shortened.

This work also allowed to detect a few (apparently harmless?) bugs in
existing code, which have been fixed already in 4.4 and main, or in this
commit as well when they depend on changes in namemap code itself.

About performances: This commit introduces a minor slow-down. Some tests
heavily relying on this code (like `bl_id_management` and `blendkernel`
e.g.) get slightly slower (resp. about 1% and 5%). This seems to come
mostly from the added complexity to handle correctly multiple different
names with the same base and numeric suffix value ('Foo.1' and
'Foo.001', but also in the global namemap context where IDs from
different libraries can have the same name).

Pull Request: https://projects.blender.org/blender/blender/pulls/135199
2025-02-28 17:58:58 +01:00

94 lines
2.9 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*
* API to ensure name uniqueness.
*
* Main database contains the UniqueName_Map which is a cache that tracks names, base
* names and their suffixes currently in use. So that whenever a new name has to be
* assigned or validated, it can quickly ensure uniqueness and adjust the name in case
* of collisions.
*
* \section Function Names
*
* - `BKE_main_namemap_` Should be used for functions in this file.
*/
#include "BLI_compiler_attrs.h"
#include "BLI_string_ref.hh"
struct ID;
struct Library;
struct Main;
struct UniqueName_Map;
/** If given pointer is not null, destroy the namemap and set the pointer to null. */
void BKE_main_namemap_destroy(UniqueName_Map **r_name_map) ATTR_NONNULL();
/**
* Destroy all name_maps in given bmain:
* - In bmain itself for local IDs.
* - In the split bmains in the list is any (for linked IDs in some cases, e.g. if called during
* readfile code).
* - In all of the libraries IDs (for linked IDs).
*/
void BKE_main_namemap_clear(Main &bmain);
/**
* Check if the given name is already in use in the whole Main data-base (local and all linked
* data).
*
* \return true if the name is already in use.
*/
bool BKE_main_global_namemap_contain_name(Main &bmain, short id_type, blender::StringRef name);
/**
* Same as #BKE_main_global_namemap_contain_name, but only search in the local or related library
* namemap.
*/
bool BKE_main_namemap_contain_name(Main &bmain,
Library *lib,
short id_type,
blender::StringRef name);
/**
* Ensures the given name is unique within the given ID type, in the whole Main data-base (local
* and all linked data).
*
* In case of name collisions, the name will be adjusted to be unique.
*
* \return true if the name had to be adjusted for uniqueness.
*/
bool BKE_main_global_namemap_get_unique_name(Main &bmain, ID &id, char *r_name);
/**
* Same as #BKE_main_global_namemap_get_name, but only make the name unique in the local or related
* library namemap.
*/
bool BKE_main_namemap_get_unique_name(Main &bmain, ID &id, char *r_name);
/**
* Remove a given name from usage.
*
* Call this whenever deleting or renaming an object.
*/
void BKE_main_namemap_remove_id(Main &bmain, ID &id);
/**
* Check that all ID names in given `bmain` are unique (per ID type and library), and that existing
* name maps are consistent with existing relevant IDs.
*
* This is typically called within an assert, or in tests.
*/
bool BKE_main_namemap_validate(Main &bmain);
/**
* Same as #BKE_main_namemap_validate, but also fixes any issue by re-generating all name maps,
* and ensuring again all ID names are unique.
*
* This is typically only used in `do_versions` code to fix broken files.
*/
bool BKE_main_namemap_validate_and_fix(Main &bmain);