dna_genfile: add SDNA struct/elem queries that use alias names

Allow versioning code to use checks which use run-time naming
instead of the old names which are only listed in dna_rename_defs.h.

Addresses T64791.
This commit is contained in:
Campbell Barton 2019-05-22 09:15:06 +10:00
parent 8accb5a46f
commit 73f7ed7ffa
Notes: blender-bot 2023-10-13 01:54:23 +02:00
Referenced by issue #64791, Use aliased names for file versioning checks
3 changed files with 160 additions and 14 deletions

View File

@ -121,4 +121,15 @@ bool DNA_sdna_patch_struct_member(struct SDNA *sdna,
void DNA_sdna_alias_data_ensure(struct SDNA *sdna);
/* Alias lookups (using runtime struct member names). */
int DNA_struct_alias_find_nr_ex(const struct SDNA *sdna,
const char *str,
unsigned int *index_last);
int DNA_struct_alias_find_nr(const struct SDNA *sdna, const char *str);
bool DNA_struct_alias_elem_find(const struct SDNA *sdna,
const char *stype,
const char *vartype,
const char *name);
void DNA_sdna_alias_data_ensure_structs_map(struct SDNA *sdna);
#endif /* __DNA_GENFILE_H__ */

View File

@ -75,6 +75,8 @@ typedef struct SDNA {
const char **names;
/** Aligned with #SDNA.types, same pointers when unchanged. */
const char **types;
/** A version of #SDNA.structs_map that uses #SDNA.alias.types for it's keys. */
struct GHash *structs_map;
} alias;
} SDNA;

View File

@ -39,9 +39,7 @@
#include "BLI_memarena.h"
#include "BLI_string.h"
#ifdef WITH_DNA_GHASH
# include "BLI_ghash.h"
#endif
#include "BLI_ghash.h"
#include "DNA_genfile.h"
#include "DNA_sdna_types.h" // for SDNA ;-)
@ -161,6 +159,11 @@ void DNA_sdna_free(SDNA *sdna)
MEM_SAFE_FREE(sdna->alias.names);
MEM_SAFE_FREE(sdna->alias.types);
#ifdef WITH_DNA_GHASH
if (sdna->alias.structs_map) {
BLI_ghash_free(sdna->alias.structs_map, NULL, NULL);
}
#endif
MEM_freeN(sdna);
}
@ -222,18 +225,29 @@ static void printstruct(SDNA *sdna, short strnr)
/**
* Returns the index of the struct info for the struct with the specified name.
*/
int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
static int dna_struct_find_nr_ex_impl(
/* From SDNA struct. */
const char **types,
const int UNUSED(types_len),
short **const structs,
const int structs_len,
#ifdef WITH_DNA_GHASH
GHash *structs_map,
#endif
/* Regular args. */
const char *str,
unsigned int *index_last)
{
if (*index_last < sdna->structs_len) {
const short *sp = sdna->structs[*index_last];
if (STREQ(sdna->types[sp[0]], str)) {
if (*index_last < structs_len) {
const short *sp = structs[*index_last];
if (STREQ(types[sp[0]], str)) {
return *index_last;
}
}
#ifdef WITH_DNA_GHASH
{
void **index_p = BLI_ghash_lookup_p(sdna->structs_map, str);
void **index_p = BLI_ghash_lookup_p(structs_map, str);
if (index_p) {
const int index = POINTER_AS_INT(*index_p);
*index_last = index;
@ -242,9 +256,9 @@ int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index
}
#else
{
for (int index = 0; index < sdna->structs_len; index++) {
const short *sp = sdna->structs[index];
if (STREQ(sdna->types[sp[0]], str)) {
for (int index = 0; index < structs_len; index++) {
const short *sp = structs[index];
if (STREQ(types[sp[0]], str)) {
*index_last = index;
return index;
}
@ -254,12 +268,58 @@ int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index
return -1;
}
/**
* Returns the index of the struct info for the struct with the specified name.
*/
int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
{
return dna_struct_find_nr_ex_impl(
/* Expand SDNA. */
sdna->types,
sdna->types_len,
sdna->structs,
sdna->structs_len,
#ifdef WITH_DNA_GHASH
sdna->structs_map,
#endif
/* Regular args. */
str,
index_last);
}
/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
int DNA_struct_alias_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
{
#ifdef WITH_DNA_GHASH
BLI_assert(sdna->alias.structs_map != NULL);
#endif
return dna_struct_find_nr_ex_impl(
/* Expand SDNA. */
sdna->alias.types,
sdna->types_len,
sdna->structs,
sdna->structs_len,
#ifdef WITH_DNA_GHASH
sdna->alias.structs_map,
#endif
/* Regular args. */
str,
index_last);
}
int DNA_struct_find_nr(const SDNA *sdna, const char *str)
{
unsigned int index_last_dummy = UINT_MAX;
return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy);
}
/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
int DNA_struct_alias_find_nr(const SDNA *sdna, const char *str)
{
unsigned int index_last_dummy = UINT_MAX;
return DNA_struct_alias_find_nr_ex(sdna, str, &index_last_dummy);
}
/* ************************* END DIV ********************** */
/* ************************* READ DNA ********************** */
@ -909,7 +969,14 @@ static int elem_strcmp(const char *name, const char *oname)
* \param old: Pointer to struct information in sdna
* \return true when existing, false otherwise.
*/
static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old)
static bool elem_exists_impl(
/* Expand SDNA. */
const char **types,
const char **names,
/* Regular args. */
const char *type,
const char *name,
const short *old)
{
int a, elemcount;
const char *otype, *oname;
@ -918,8 +985,8 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co
elemcount = old[1];
old += 2;
for (a = 0; a < elemcount; a++, old += 2) {
otype = sdna->types[old[0]];
oname = sdna->names[old[1]];
otype = types[old[0]];
oname = names[old[1]];
if (elem_strcmp(name, oname) == 0) { /* name equal */
return strcmp(type, otype) == 0; /* type equal */
@ -928,6 +995,33 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co
return false;
}
static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old)
{
return elem_exists_impl(
/* Expand SDNA. */
sdna->types,
sdna->names,
/* Regular args. */
type,
name,
old);
}
static bool elem_exists_alias(const SDNA *sdna,
const char *type,
const char *name,
const short *old)
{
return elem_exists_impl(
/* Expand SDNA. */
sdna->alias.types,
sdna->alias.names,
/* Regular args. */
type,
name,
old);
}
/**
* Returns the address of the data for the specified field within olddata
* according to the struct format pointed to by old, or NULL if no such
@ -1384,6 +1478,25 @@ bool DNA_struct_elem_find(const SDNA *sdna,
return false;
}
/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
bool DNA_struct_alias_elem_find(const SDNA *sdna,
const char *stype,
const char *vartype,
const char *name)
{
const int SDNAnr = DNA_struct_alias_find_nr(sdna, stype);
if (SDNAnr != -1) {
const short *const spo = sdna->structs[SDNAnr];
const bool found = elem_exists_alias(sdna, vartype, name, spo);
if (found) {
return true;
}
}
return false;
}
/**
* Returns the size in bytes of a primitive type.
*/
@ -1629,4 +1742,24 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna)
BLI_ghash_free(elem_map_alias_from_static, MEM_freeN, NULL);
}
/**
* Separated from #DNA_sdna_alias_data_ensure because it's not needed
* unless we want to lookup aliased struct names (#DNA_struct_alias_find_nr and friends).
*/
void DNA_sdna_alias_data_ensure_structs_map(SDNA *sdna)
{
DNA_sdna_alias_data_ensure(sdna);
#ifdef WITH_DNA_GHASH
/* create a ghash lookup to speed up */
struct GHash *structs_map = BLI_ghash_str_new_ex(__func__, sdna->structs_len);
for (intptr_t nr = 0; nr < sdna->structs_len; nr++) {
const short *sp = sdna->structs[nr];
BLI_ghash_insert(structs_map, (void *)sdna->alias.types[sp[0]], POINTER_FROM_INT(nr));
}
sdna->alias.structs_map = structs_map;
#else
UNUSED_VARS(sdna);
#endif
}
/** \} */