Compare commits

...

15 Commits

Author SHA1 Message Date
7506e19220 Naming 2019-02-13 10:47:18 +11:00
dea9aa1591 Rename 'elem_dna' to 'elem_full' 2019-02-13 10:34:44 +11:00
35b0e1f513 Detect duplicate names 2019-02-13 10:31:43 +11:00
3c0fced71e Rename var, comments 2019-02-13 08:46:02 +11:00
acab81f2b5 Correct naming 2019-02-13 08:42:25 +11:00
5ff64cc9d2 Rename softupdate -> softpatch 2019-02-13 08:10:01 +11:00
3cf2ad0f75 Correct mistakes, also simplify names 2019-02-13 07:58:18 +11:00
97c3005ec9 Remove TODO 2019-02-13 01:21:09 +11:00
d76db3deed Use RNA ifdef's 2019-02-13 01:13:07 +11:00
c234a35ab0 Use new struct names in versioning_dna.c 2019-02-13 01:06:17 +11:00
5040c77bdb Utility to apply edits 2019-02-13 00:39:32 +11:00
9d77721972 More renaming 2019-02-13 00:38:53 +11:00
fc4d4727b0 Correct missing files 2019-02-13 00:31:29 +11:00
823ebbae65 Minor edits 2019-02-13 00:15:41 +11:00
783f3376ee Reviewers: brecht mont29 sergey dflinto
Differential Revision: https://developer.blender.org/D4342
2019-02-12 23:52:17 +11:00
10 changed files with 567 additions and 70 deletions

View File

@@ -16,18 +16,49 @@
/** \file \ingroup blenloader
*
* Apply edits to DNA at load time
* to behave as if old files were written new names.
* Support for version patching DNA, there are two kinds.
*
* - #DNA_MAKESDNA defined:
* Defines store files with old names but run-time uses new names.
*
* Allows us to rename variables & structs without breaking compatibility.
*
* - #DNA_MAKESDNA undefined:
* Behave as if old files were written new names.
*
* This means older versions of Blender won't have access to this data *USE WITH CARE*.
*
*/
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#ifndef DNA_MAKESDNA
# include "BLI_compiler_attrs.h"
# include "BLI_utildefines.h"
#include "DNA_genfile.h"
#include "DNA_listBase.h"
# include "DNA_genfile.h"
# include "DNA_listBase.h"
#include "BLO_readfile.h"
#include "readfile.h"
# include "BLO_readfile.h"
# include "readfile.h"
#endif
#ifdef DNA_MAKESDNA
/**
* Included in DNA versioning code.
*
* Currently use 'new' names when replacing struct members.
*/
DNA_STRUCT_REPLACE(Lamp, Light)
DNA_STRUCT_MEMBER_REPLACE(Light, clipsta, clip_start)
DNA_STRUCT_MEMBER_REPLACE(Light, clipend, clip_end)
DNA_STRUCT_MEMBER_REPLACE(LightProbe, clipsta, clip_start)
DNA_STRUCT_MEMBER_REPLACE(LightProbe, clipend, clip_end)
DNA_STRUCT_MEMBER_REPLACE(Camera, clipsta, clip_start)
DNA_STRUCT_MEMBER_REPLACE(Camera, clipend, clip_end)
DNA_STRUCT_MEMBER_REPLACE(Camera, YF_dofdist, dof_dist)
#else /* !DNA_MAKESDNA */
/**
* Manipulates SDNA before calling #DNA_struct_get_compareflags,
@@ -57,3 +88,5 @@ void blo_do_versions_dna(SDNA *sdna, const int versionfile, const int subversion
#undef DNA_VERSION_ATLEAST
}
#endif /* !DNA_MAKESDNA */

View File

@@ -109,4 +109,6 @@ bool DNA_sdna_patch_struct(
bool DNA_sdna_patch_struct_member(
struct SDNA *sdna, const char *struct_name, const char *member_old, const char *member_new);
void DNA_sdna_softpatch_runtime_ensure(struct SDNA *sdna);
#endif /* __DNA_GENFILE_H__ */

View File

@@ -64,6 +64,14 @@ typedef struct SDNA {
/** Temporary memory currently only used for version patching DNA. */
struct MemArena *mem_arena;
/** Runtime versions of data stored in DNA, lazy initialized,
* only different when renaming is done. */
struct {
/** Aligned with #SDNA.names, same pointers when unchanged. */
const char **names;
/** Aligned with #SDNA.types, same pointers when unchanged. */
const char **types;
} runtime;
} SDNA;
#

View File

@@ -35,7 +35,11 @@ blender_include_dirs(
set(SRC
dna_utils.c
makesdna.c
../../blenlib/intern/BLI_ghash.c
../../blenlib/intern/BLI_ghash_utils.c
../../blenlib/intern/BLI_memarena.c
../../blenlib/intern/BLI_mempool.c
../../blenlib/intern/hash_mm2a.c # needed by 'BLI_ghash_utils.c', not used directly.
../../../../intern/guardedalloc/intern/mallocn.c
../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c
../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c

View File

@@ -156,6 +156,9 @@ void DNA_sdna_free(SDNA *sdna)
BLI_memarena_free(sdna->mem_arena);
}
MEM_SAFE_FREE(sdna->runtime.names);
MEM_SAFE_FREE(sdna->runtime.types);
MEM_freeN(sdna);
}
@@ -311,6 +314,9 @@ static bool init_structDNA(
#endif
sdna->mem_arena = NULL;
/* Lazy initialize. */
memset(&sdna->runtime, 0, sizeof(sdna->runtime));
/* Struct DNA ('SDNA') */
if (*data != MAKE_ID('S', 'D', 'N', 'A')) {
*r_error_message = "SDNA error in SDNA file";
@@ -1402,22 +1408,22 @@ static bool DNA_sdna_patch_struct_member_nr(
BLI_assert(member_new != NULL);
const short *sp = sdna->structs[struct_name_nr];
for (int member_iter = sp[1]; member_iter > 0; member_iter--, sp += 2) {
const char *member_dna_old = sdna->names[sp[1]];
/* Start & end offsets in 'member_dna_old'. */
uint member_dna_offset_start;
if (DNA_elem_id_match(member_old, member_old_len, member_dna_old, &member_dna_offset_start)) {
const char *elem_full_old = sdna->names[sp[1]];
/* Start & end offsets in 'elem_full_old'. */
uint elem_full_offset_start;
if (DNA_elem_id_match(member_old, member_old_len, elem_full_old, &elem_full_offset_start)) {
if (sdna->mem_arena == NULL) {
sdna->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
const int member_dna_old_len = strlen(member_dna_old);
const char *member_dna_new = DNA_elem_id_rename(
const int elem_full_old_len = strlen(elem_full_old);
const char *elem_full_new = DNA_elem_id_rename(
sdna->mem_arena,
member_old, member_old_len,
member_new, member_new_len,
member_dna_old, member_dna_old_len,
member_dna_offset_start);
elem_full_old, elem_full_old_len,
elem_full_offset_start);
sdna->names[sp[1]] = member_dna_new;
sdna->names[sp[1]] = elem_full_new;
return true;
}
}
@@ -1438,3 +1444,113 @@ bool DNA_sdna_patch_struct_member(
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Versioning (Forward Compatible)
*
* Versioning that allows new names.
* \{ */
/**
* Names are shared between structs which causes problems renaming.
* Make sure every struct member gets it's own name so renaming only ever impacts a single struct.
*/
static void sdna_softpatch_runtime_expand_names(SDNA *sdna)
{
int names_expand_len = 0;
for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
const short *sp = sdna->structs[struct_nr];
names_expand_len += sp[1];
}
const char **names_expand = MEM_mallocN(sizeof(*names_expand) * names_expand_len, __func__);
int names_expand_index = 0;
for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
/* We can't edit this memory 'sdna->structs' points to (readonly datatoc file). */
const short *sp = sdna->structs[struct_nr];
short *sp_expand = BLI_memarena_alloc(sdna->mem_arena, sizeof(short[2]) * (1 + sp[1]));
memcpy(sp_expand, sp, sizeof(short[2]) * (1 + sp[1]));
sdna->structs[struct_nr] = sp_expand;
const int names_len = sp[1];
sp += 2;
sp_expand += 2;
for (int i = 0; i < names_len; i++, sp += 2, sp_expand += 2) {
names_expand[names_expand_index] = sdna->names[sp[1]];
BLI_assert(names_expand_index < SHRT_MAX);
sp_expand[1] = names_expand_index;
names_expand_index++;
}
}
MEM_freeN((void *)sdna->names);
sdna->names = names_expand;
sdna->nr_names = names_expand_len;
}
void DNA_sdna_softpatch_runtime_ensure(SDNA *sdna)
{
if (sdna->mem_arena == NULL) {
sdna->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
}
GHash *struct_map_runtime_from_static;
GHash *elem_map_runtime_from_static;
DNA_softpatch_maps(
DNA_VERSION_RUNTIME_FROM_STATIC,
&struct_map_runtime_from_static,
&elem_map_runtime_from_static);
if (sdna->runtime.types == NULL) {
sdna->runtime.types = MEM_mallocN(sizeof(*sdna->runtime.types) * sdna->nr_types, __func__);
for (int type_nr = 0; type_nr < sdna->nr_types; type_nr++) {
const char *str = sdna->types[type_nr];
sdna->runtime.types[type_nr] = BLI_ghash_lookup_default(
struct_map_runtime_from_static, str, (void *)str);
}
}
if (sdna->runtime.names == NULL) {
sdna_softpatch_runtime_expand_names(sdna);
sdna->runtime.names = MEM_mallocN(sizeof(*sdna->runtime.names) * sdna->nr_names, __func__);
for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
const short *sp = sdna->structs[struct_nr];
const char *struct_name_static = sdna->types[sp[0]];
const int dna_struct_names_len = sp[1];
sp += 2;
for (int a = 0; a < dna_struct_names_len; a++, sp += 2) {
const char *elem_static = sdna->names[sp[1]];
const uint elem_static_offset_start = DNA_elem_id_offset_start(elem_static);
const char *elem_static_trim = elem_static + elem_static_offset_start;
const uint elem_full_offset_end = (
elem_static_offset_start + DNA_elem_id_offset_end(elem_static_trim));
const uint elem_static_buf_len = elem_full_offset_end - elem_static_offset_start;
char elem_static_buf[1024];
strncpy(elem_static_buf, elem_static_trim, elem_static_buf_len);
elem_static_buf[elem_static_buf_len] = '\0';
// printf("Searching '%s.%s'\n", struct_name_static, elem_static_buf);
const char *str_pair[2] = {struct_name_static, elem_static_buf};
const char *elem_runtime = BLI_ghash_lookup(elem_map_runtime_from_static, str_pair);
if (elem_runtime) {
// printf("Found %s from %s\n", elem_runtime, elem_static_buf);
sdna->runtime.names[sp[1]] = DNA_elem_id_rename(
sdna->mem_arena,
elem_static_trim, strlen(elem_static_trim),
elem_runtime, strlen(elem_runtime),
elem_static, strlen(elem_static),
elem_static_offset_start);
// printf("result is: %s\n", sdna->runtime.names[sp[1]]);
}
else {
sdna->runtime.names[sp[1]] = sdna->names[sp[1]];
}
}
}
}
BLI_ghash_free(struct_map_runtime_from_static, NULL, NULL);
BLI_ghash_free(elem_map_runtime_from_static, MEM_freeN, NULL);
}
/** \} */

View File

@@ -23,9 +23,12 @@
#include <string.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h"
#include "BLI_utildefines.h"
#include "BLI_assert.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
@@ -86,22 +89,34 @@ static bool is_identifier(const char c)
(c == '_'));
}
uint DNA_elem_id_offset_start(const char *elem_dna)
uint DNA_elem_id_offset_start(const char *elem_full)
{
uint elem_dna_offset = 0;
while (!is_identifier(elem_dna[elem_dna_offset])) {
elem_dna_offset++;
uint elem_full_offset = 0;
while (!is_identifier(elem_full[elem_full_offset])) {
elem_full_offset++;
}
return elem_dna_offset;
return elem_full_offset;
}
uint DNA_elem_id_offset_end(const char *elem_dna)
uint DNA_elem_id_offset_end(const char *elem_full)
{
uint elem_dna_offset = 0;
while (is_identifier(elem_dna[elem_dna_offset])) {
elem_dna_offset++;
uint elem_full_offset = 0;
while (is_identifier(elem_full[elem_full_offset])) {
elem_full_offset++;
}
return elem_dna_offset;
return elem_full_offset;
}
/**
* \a elem_dst must be at least the size of \a elem_src.
*/
void DNA_elem_id_strip(char *elem_dst, const char *elem_src)
{
const uint elem_src_offset = DNA_elem_id_offset_start(elem_src);
const char *elem_src_trim = elem_src + elem_src_offset;
const uint elem_src_trim_len = DNA_elem_id_offset_end(elem_src_trim);
memcpy(elem_dst, elem_src_trim, elem_src_trim_len);
elem_dst[elem_src_trim_len] = '\0';
}
/**
@@ -110,16 +125,16 @@ uint DNA_elem_id_offset_end(const char *elem_dna)
*/
bool DNA_elem_id_match(
const char *elem_search, const int elem_search_len,
const char *elem_dna,
uint *r_elem_dna_offset)
const char *elem_full,
uint *r_elem_full_offset)
{
BLI_assert(strlen(elem_search) == elem_search_len);
const uint elem_dna_offset = DNA_elem_id_offset_start(elem_dna);
const char *elem_dna_trim = elem_dna + elem_dna_offset;
if (strncmp(elem_search, elem_dna_trim, elem_search_len) == 0) {
const char c = elem_dna_trim[elem_search_len];
const uint elem_full_offset = DNA_elem_id_offset_start(elem_full);
const char *elem_full_trim = elem_full + elem_full_offset;
if (strncmp(elem_search, elem_full_trim, elem_search_len) == 0) {
const char c = elem_full_trim[elem_search_len];
if (c == '\0' || !is_identifier(c)) {
*r_elem_dna_offset = elem_dna_offset;
*r_elem_full_offset = elem_full_offset;
return true;
}
}
@@ -133,32 +148,125 @@ char *DNA_elem_id_rename(
struct MemArena *mem_arena,
const char *elem_src, const int elem_src_len,
const char *elem_dst, const int elem_dst_len,
const char *elem_dna_src, const int elem_dna_src_len,
const uint elem_dna_offset_start)
const char *elem_full_src, const int elem_full_src_len,
const uint elem_full_offset_start)
{
BLI_assert(strlen(elem_src) == elem_src_len);
BLI_assert(strlen(elem_dst) == elem_dst_len);
BLI_assert(strlen(elem_dna_src) == elem_dna_src_len);
BLI_assert(DNA_elem_id_offset_start(elem_dna_src) == elem_dna_offset_start);
BLI_assert(strlen(elem_full_src) == elem_full_src_len);
BLI_assert(DNA_elem_id_offset_start(elem_full_src) == elem_full_offset_start);
UNUSED_VARS_NDEBUG(elem_src);
const int elem_final_len = (elem_dna_src_len - elem_src_len) + elem_dst_len;
char *elem_dna_dst = BLI_memarena_alloc(mem_arena, elem_final_len + 1);
const int elem_final_len = (elem_full_src_len - elem_src_len) + elem_dst_len;
char *elem_full_dst = BLI_memarena_alloc(mem_arena, elem_final_len + 1);
uint i = 0;
if (elem_dna_offset_start != 0) {
memcpy(elem_dna_dst, elem_dna_src, elem_dna_offset_start);
i = elem_dna_offset_start;
if (elem_full_offset_start != 0) {
memcpy(elem_full_dst, elem_full_src, elem_full_offset_start);
i = elem_full_offset_start;
}
memcpy(&elem_dna_dst[i], elem_dst, elem_dst_len + 1);
memcpy(&elem_full_dst[i], elem_dst, elem_dst_len + 1);
i += elem_dst_len;
uint elem_dna_offset_end = elem_dna_offset_start + elem_src_len;
if (elem_dna_src[elem_dna_offset_end] != '\0') {
const int elem_dna_tail_len = (elem_dna_src_len - elem_dna_offset_end);
memcpy(&elem_dna_dst[i], &elem_dna_src[elem_dna_offset_end], elem_dna_tail_len + 1);
i += elem_dna_tail_len;
uint elem_full_offset_end = elem_full_offset_start + elem_src_len;
if (elem_full_src[elem_full_offset_end] != '\0') {
const int elem_full_tail_len = (elem_full_src_len - elem_full_offset_end);
memcpy(&elem_full_dst[i], &elem_full_src[elem_full_offset_end], elem_full_tail_len + 1);
i += elem_full_tail_len;
}
BLI_assert((strlen(elem_dna_dst) == elem_final_len) && (i == elem_final_len));
return elem_dna_dst;
BLI_assert((strlen(elem_full_dst) == elem_final_len) && (i == elem_final_len));
return elem_full_dst;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Versioning
* \{ */
/* Use for #DNA_VERSIONING_INCLUDE */
#define DNA_MAKESDNA
static uint strhash_pair_p(const void *ptr)
{
const char * const *pair = ptr;
return (BLI_ghashutil_strhash_p(pair[0]) ^
BLI_ghashutil_strhash_p(pair[1]));
}
static bool strhash_pair_cmp(const void *a, const void *b)
{
const char * const *pair_a = a;
const char * const *pair_b = b;
return (STREQ(pair_a[0], pair_b[0]) &&
STREQ(pair_a[1], pair_b[1])) ? false : true;
}
void DNA_softpatch_maps(
enum eDNAVersionDir version_dir,
GHash **r_struct_map, GHash **r_elem_map)
{
GHash *struct_map_local;
if (r_struct_map) {
const char *data[][2] = {
#define DNA_STRUCT_REPLACE(old, new) {#old, #new},
#define DNA_STRUCT_MEMBER_REPLACE(struct_name, old, new)
#include DNA_VERSIONING_DEFINES
#undef DNA_STRUCT_REPLACE
#undef DNA_STRUCT_MEMBER_REPLACE
};
int elem_key, elem_val;
if (version_dir == DNA_VERSION_RUNTIME_FROM_STATIC) {
elem_key = 0;
elem_val = 1;
}
else {
elem_key = 1;
elem_val = 0;
}
GHash *struct_map = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(data));
for (int i = 0; i < ARRAY_SIZE(data); i++) {
BLI_ghash_insert(struct_map, (void *)data[i][elem_key], (void *)data[i][elem_val]);
}
*r_struct_map = struct_map;
/* We know the direction of this, for local use. */
struct_map_local = BLI_ghash_str_new_ex(__func__, ARRAY_SIZE(data));
for (int i = 0; i < ARRAY_SIZE(data); i++) {
BLI_ghash_insert(struct_map_local, (void *)data[i][1], (void *)data[i][0]);
}
}
if (r_elem_map != NULL) {
const char *data[][3] = {
#define DNA_STRUCT_REPLACE(old, new)
#define DNA_STRUCT_MEMBER_REPLACE(struct_name, old, new) {#struct_name, #old, #new},
#include DNA_VERSIONING_DEFINES
#undef DNA_STRUCT_REPLACE
#undef DNA_STRUCT_MEMBER_REPLACE
};
int elem_key, elem_val;
if (version_dir == DNA_VERSION_RUNTIME_FROM_STATIC) {
elem_key = 1;
elem_val = 2;
}
else {
elem_key = 2;
elem_val = 1;
}
GHash *elem_map = BLI_ghash_new_ex(strhash_pair_p, strhash_pair_cmp, __func__, ARRAY_SIZE(data));
for (int i = 0; i < ARRAY_SIZE(data); i++) {
const char **str_pair = MEM_mallocN(sizeof(char *) * 2, __func__);
str_pair[0] = BLI_ghash_lookup_default(struct_map_local, data[i][0], (void *)data[i][0]);
str_pair[1] = data[i][elem_key],
BLI_ghash_insert(elem_map, str_pair, (void *)data[i][elem_val]);
}
*r_elem_map = elem_map;
}
BLI_ghash_free(struct_map_local, NULL, NULL);
}
#undef DNA_MAKESDNA
/** \} */

View File

@@ -21,20 +21,34 @@
#define __DNA_UTILS_H__
struct MemArena;
struct GHash;
int DNA_elem_array_size(const char *str);
uint DNA_elem_id_offset_start(const char *elem_dna);
uint DNA_elem_id_offset_end(const char *elem_dna);
uint DNA_elem_id_offset_start(const char *elem_full);
uint DNA_elem_id_offset_end(const char *elem_full);
void DNA_elem_id_strip(char *elem_dst, const char *elem_src);
bool DNA_elem_id_match(
const char *elem_search, const int elem_search_len,
const char *elem_dna,
uint *r_elem_dna_offset);
const char *elem_full,
uint *r_elem_full_offset);
char *DNA_elem_id_rename(
struct MemArena *mem_arena,
const char *elem_src, const int elem_src_len,
const char *elem_dst, const int elem_dst_len,
const char *elem_dna_src, const int elem_dna_src_len,
const uint elem_dna_offset_start);
const char *elem_full_src, const int elem_full_src_len,
const uint elem_full_offset_start);
/* When requesting version info, support both directions. */
enum eDNAVersionDir {
DNA_VERSION_STATIC_FROM_RUNTIME = -1,
DNA_VERSION_RUNTIME_FROM_STATIC = 1,
};
void DNA_softpatch_maps(
enum eDNAVersionDir version_dir,
struct GHash **r_struct_map, struct GHash **r_elem_map);
/* Needs 'DNA_MAKESDNA' to be defined. */
#define DNA_VERSIONING_DEFINES "../../blenloader/intern/versioning_dna.c"
#endif /* __DNA_UTILS_H__ */

View File

@@ -43,11 +43,15 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "MEM_guardedalloc.h"
#include "BLI_sys_types.h" /* for intptr_t support */
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
#include "BLI_sys_types.h" /* for intptr_t support */
#include "dna_utils.h"
@@ -153,6 +157,14 @@ static short *typelens_64;
* sp[1] is amount of elements
* sp[2] sp[3] is typenr, namenr (etc) */
static short **structs, *structdata;
/** Versioning data */
static struct {
GHash *struct_map_runtime_from_static;
GHash *struct_map_static_from_runtime;
GHash *elem_map_static_from_runtime;
} g_version_data = {NULL};
/**
* Variable to control debug output of makesdna.
* debugSDNA:
@@ -167,10 +179,8 @@ static int additional_slen_offset;
#define DEBUG_PRINTF(debug_level, ...) \
{ if (debugSDNA > debug_level) { printf(__VA_ARGS__); } } ((void)0)
/* stub for BLI_abort() */
#ifndef NDEBUG
void BLI_system_backtrace(FILE *fp);
void BLI_system_backtrace(FILE *fp)
{
(void)fp;
@@ -234,6 +244,49 @@ void printStructLengths(void);
/* ************************* MAKEN DNA ********************** */
static const char *version_struct_static_from_runtime(const char *str)
{
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_static_from_runtime, str);
if (str_test != NULL) {
return str_test;
}
return str;
}
static const char *version_struct_runtime_from_static(const char *str)
{
const char *str_test = BLI_ghash_lookup(g_version_data.struct_map_runtime_from_static, str);
if (str_test != NULL) {
return str_test;
}
return str;
}
static const char *version_elem_static_from_runtime(
const int strct, const char *elem_runtime_full)
{
/* First get the old name with everything stripped out of it. */
const uint elem_runtime_offset_start = DNA_elem_id_offset_start(elem_runtime_full);
const char *elem_runtime_trim = elem_runtime_full + elem_runtime_offset_start;
const uint elem_runtime_len = DNA_elem_id_offset_end(elem_runtime_trim);
char *elem_runtime = alloca(elem_runtime_len + 1);
memcpy(elem_runtime, elem_runtime_trim, elem_runtime_len);
elem_runtime[elem_runtime_len] = '\0';
const char *str_pair[2] = {types[strct], elem_runtime};
const char *elem_static = BLI_ghash_lookup(g_version_data.elem_map_static_from_runtime, str_pair);
if (elem_static != NULL) {
return DNA_elem_id_rename(
mem_arena,
elem_runtime, strlen(elem_runtime),
elem_static, strlen(elem_static),
elem_runtime, elem_runtime_len,
elem_runtime_offset_start);
}
return elem_runtime_full;
}
static int add_type(const char *str, int len)
{
int nr;
@@ -249,6 +302,8 @@ static int add_type(const char *str, int len)
return -1;
}
str = version_struct_static_from_runtime(str);
/* search through type array */
for (nr = 0; nr < nr_types; nr++) {
if (strcmp(str, types[nr]) == 0) {
@@ -668,8 +723,7 @@ static int convert_include(const char *filename)
if (md1[slen - 1] == ';') {
md1[slen - 1] = 0;
name = add_name(md1);
name = add_name(version_elem_static_from_runtime(strct, md1));
slen += additional_slen_offset;
sp[0] = type;
sp[1] = name;
@@ -685,8 +739,7 @@ static int convert_include(const char *filename)
break;
}
name = add_name(md1);
name = add_name(version_elem_static_from_runtime(strct, md1));
slen += additional_slen_offset;
sp[0] = type;
@@ -975,7 +1028,7 @@ void printStructLengths(void)
static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offsets)
{
int len, i;
int i;
const short *sp;
/* str contains filenames. Since we now include paths, I stretched */
/* it a bit. Hope this is enough :) -nzc- */
@@ -1000,6 +1053,16 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
typelens_64 = MEM_callocN(sizeof(short) * maxnr, "typelens_64");
structs = MEM_callocN(sizeof(short *) * maxnr, "structs");
/* Build versioning data */
DNA_softpatch_maps(
DNA_VERSION_RUNTIME_FROM_STATIC,
&g_version_data.struct_map_runtime_from_static,
NULL);
DNA_softpatch_maps(
DNA_VERSION_STATIC_FROM_RUNTIME,
&g_version_data.struct_map_static_from_runtime,
&g_version_data.elem_map_static_from_runtime);
/**
* Insertion of all known types.
*
@@ -1085,7 +1148,7 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
}
else {
const char nil_bytes[4] = {0};
int len_align;
int len, len_align;
dna_write(file, "SDNA", 4);
@@ -1182,12 +1245,42 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
for (i = 0; i < nr_structs; i++) {
const short *structpoin = structs[i];
const int structtype = structpoin[0];
fprintf(file_offsets, "\t_SDNA_TYPE_%s = %d,\n", types[structtype], i);
fprintf(file_offsets, "\t_SDNA_TYPE_%s = %d,\n", version_struct_runtime_from_static(types[structtype]), i);
}
fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", nr_structs);
fprintf(file_offsets, "};\n");
}
/* Check versioning errors which could cause duplicate names,
* do last because names are stripped. */
{
GSet *names_unique = BLI_gset_str_new_ex(__func__, 512);
char name_buf[512];
for (int struct_nr = 0; struct_nr < nr_structs; struct_nr++) {
sp = structs[struct_nr];
const char *struct_name = types[sp[0]];
const int len = sp[1];
sp += 2;
for (int a = 0; a < len; a++, sp += 2) {
char *name = names[sp[1]];
const int name_len = strlen(name);
BLI_assert(name_len < sizeof(name_buf));
DNA_elem_id_strip(name_buf, name);
strcpy(name, name_buf);
if (!BLI_gset_add(names_unique, name)) {
fprintf(stderr, "Error: duplicate name found '%s.%s', "
"likely cause is 'versioning_dna.c'\n",
struct_name, name);
return 1;
}
}
BLI_gset_clear(names_unique, NULL);
}
BLI_gset_free(names_unique, NULL);
}
MEM_freeN(structdata);
MEM_freeN(names);
MEM_freeN(types);
@@ -1198,6 +1291,10 @@ static int make_structDNA(const char *baseDirectory, FILE *file, FILE *file_offs
BLI_memarena_free(mem_arena);
BLI_ghash_free(g_version_data.struct_map_runtime_from_static, NULL, NULL);
BLI_ghash_free(g_version_data.struct_map_static_from_runtime, NULL, NULL);
BLI_ghash_free(g_version_data.elem_map_static_from_runtime, MEM_freeN, NULL);
DEBUG_PRINTF(0, "done.\n");
return(0);

View File

@@ -58,6 +58,12 @@
BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
#ifndef RNA_RUNTIME
static struct {
GHash *struct_map_static_from_runtime;
} g_version_data;
#endif
/* Duplicated code since we can't link in blenkernel or blenlib */
/* pedantic check for final '.', note '...' are allowed though. */
@@ -354,7 +360,19 @@ static int rna_find_sdna_member(SDNA *sdna, const char *structname, const char *
const short *sp;
int a, b, structnr, totmember, cmp;
structnr = DNA_struct_find_nr(sdna, structname);
if (!DefRNA.preprocess) {
fprintf(stderr, "%s: only during preprocessing.\n", __func__);
return 0;
}
#ifndef RNA_RUNTIME
{
const char *structname_maybe_static = BLI_ghash_lookup_default(
g_version_data.struct_map_static_from_runtime, structname, (void *)structname);
structnr = DNA_struct_find_nr(sdna, structname_maybe_static);
}
#endif
if (structnr == -1)
return 0;
@@ -363,8 +381,7 @@ static int rna_find_sdna_member(SDNA *sdna, const char *structname, const char *
sp += 2;
for (a = 0; a < totmember; a++, sp += 2) {
dnaname = sdna->names[sp[1]];
dnaname = sdna->runtime.names[sp[1]];
cmp = rna_member_cmp(dnaname, membername);
if (cmp == 1) {
@@ -572,6 +589,16 @@ BlenderRNA *RNA_create(void)
DefRNA.error = 1;
}
/* We need both runtime and static (on-disk) DNA names. */
DNA_sdna_softpatch_runtime_ensure(DefRNA.sdna);
#ifndef RNA_RUNTIME
DNA_softpatch_maps(
DNA_VERSION_STATIC_FROM_RUNTIME,
&g_version_data.struct_map_static_from_runtime,
NULL);
#endif
return brna;
}
@@ -705,6 +732,12 @@ void RNA_free(BlenderRNA *brna)
RNA_struct_free(brna, srna);
}
}
#ifndef RNA_RUNTIME
BLI_ghash_free(g_version_data.struct_map_static_from_runtime, NULL, NULL);
g_version_data.struct_map_static_from_runtime = NULL;
#endif
}
static size_t rna_property_type_sizeof(PropertyType type)

82
version_update_D4342_utility.py Executable file
View File

@@ -0,0 +1,82 @@
#!/usr/bin/env python3
# Run from Blender's root DIR
SOURCE_DIRS = (
"source",
)
USE_MULTIPROCESS = True
replace_all = (
("clipsta", "clip_start"),
("clipend", "clip_end"),
("YF_dofdist", "dof_dist"),
("Lamp", "Light"),
)
replace_tables = (
replace_all,
)
replace_tables_re = [
[(src, dst) for src, dst in table]
for table in replace_tables
]
def replace_all(fn, data_src):
import re
data_dst = data_src
for table in replace_tables_re:
for src_re, dst in table:
data_dst = re.sub(src_re, dst, data_dst)
return data_dst
operation = replace_all
import os
def source_files(path):
for dirpath, dirnames, filenames in os.walk(path):
dirnames[:] = [d for d in dirnames if not d.startswith(".")]
for filename in filenames:
if filename.startswith("."):
continue
ext = os.path.splitext(filename)[1]
# XXX weak, don't touch this!
if filename.endswith("versioning_dna.c"):
continue
if ext.lower() in {".c", ".cc", ".cxx", ".cpp", ".h", ".hxx", ".hpp"}:
yield os.path.join(dirpath, filename)
def operation_wrap(fn):
with open(fn, "r", encoding="utf-8") as f:
data_src = f.read()
data_dst = operation(fn, data_src)
if data_dst is None or (data_src == data_dst):
return
with open(fn, "w", encoding="utf-8") as f:
f.write(data_dst)
def main():
if USE_MULTIPROCESS:
args = [fn for DIR in SOURCE_DIRS for fn in source_files(DIR)]
import multiprocessing
job_total = multiprocessing.cpu_count()
pool = multiprocessing.Pool(processes=job_total * 2)
pool.map(operation_wrap, args)
else:
for fn in source_files(SOURCE_DIR):
operation_wrap(fn)
if __name__ == "__main__":
main()