From f04bc75f8ce0dbef36f440ff3f840c54de9fda12 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 31 Jan 2024 17:08:09 +0100 Subject: [PATCH] Cleanup: Use std::string for some RNA function return values This significantly simplifies memory management, mostly by avoiding the need to free the memory manually. It may also improve performance, since std::string has an inline buffer that can prevent heap allocations and it stores the size. Pull Request: https://projects.blender.org/blender/blender/pulls/117695 --- source/blender/animrig/intern/keyframing.cc | 7 +- .../blender/animrig/intern/keyframing_auto.cc | 8 +- source/blender/blenkernel/BKE_key.hh | 5 +- source/blender/blenkernel/intern/action.cc | 12 +- source/blender/blenkernel/intern/fcurve.cc | 17 +- source/blender/blenkernel/intern/key.cc | 12 +- .../depsgraph/intern/depsgraph_query.cc | 7 +- .../animation/anim_channels_defines.cc | 138 ++++---- .../editors/animation/anim_channels_edit.cc | 23 +- .../blender/editors/animation/anim_filter.cc | 11 +- source/blender/editors/animation/drivers.cc | 39 +-- .../blender/editors/animation/keyframing.cc | 33 +- .../blender/editors/animation/keyingsets.cc | 18 +- source/blender/editors/armature/pose_utils.cc | 2 +- .../blender/editors/include/UI_interface_c.hh | 2 +- .../eyedroppers/eyedropper_driver.cc | 17 +- .../editors/interface/interface_anim.cc | 10 +- .../interface/interface_context_menu.cc | 16 +- .../editors/interface/interface_handlers.cc | 12 +- .../editors/interface/interface_ops.cc | 94 +++--- .../interface/interface_region_tooltip.cc | 9 +- .../editors/object/object_constraint.cc | 10 +- .../editors/space_console/space_console.cc | 5 +- .../blender/editors/space_node/node_group.cc | 26 +- .../blender/editors/space_text/space_text.cc | 6 +- source/blender/makesrna/RNA_access.hh | 42 +-- source/blender/makesrna/RNA_path.hh | 70 +++-- source/blender/makesrna/intern/CMakeLists.txt | 2 + source/blender/makesrna/intern/rna_access.cc | 183 +++++------ .../intern/rna_access_compare_override.cc | 79 +++-- source/blender/makesrna/intern/rna_color.cc | 6 +- source/blender/makesrna/intern/rna_path.cc | 296 ++++++++---------- source/blender/python/intern/bpy_rna.cc | 46 +-- source/blender/python/intern/bpy_rna_anim.cc | 12 +- .../windowmanager/intern/wm_event_system.cc | 7 +- .../windowmanager/intern/wm_operators.cc | 43 +-- .../message_bus/intern/wm_message_bus_rna.cc | 5 +- 37 files changed, 591 insertions(+), 739 deletions(-) diff --git a/source/blender/animrig/intern/keyframing.cc b/source/blender/animrig/intern/keyframing.cc index ca6b2eb0801..4a8c830b712 100644 --- a/source/blender/animrig/intern/keyframing.cc +++ b/source/blender/animrig/intern/keyframing.cc @@ -948,19 +948,18 @@ void insert_key_rna(PointerRNA *rna_pointer, rna_path.c_str()); continue; } - char *rna_path_id_to_prop = RNA_path_from_ID_to_property(&ptr, prop); + const std::optional rna_path_id_to_prop = RNA_path_from_ID_to_property(&ptr, + prop); Vector rna_values = get_keyframe_values(&ptr, prop, visual_keyframing); insert_key_count += insert_key_action(bmain, action, rna_pointer, - rna_path_id_to_prop, + rna_path_id_to_prop->c_str(), nla_frame, rna_values.as_span(), insert_key_flags, key_type); - - MEM_freeN(rna_path_id_to_prop); } if (insert_key_count == 0) { diff --git a/source/blender/animrig/intern/keyframing_auto.cc b/source/blender/animrig/intern/keyframing_auto.cc index 94f01ec86fb..dcbf5649b7e 100644 --- a/source/blender/animrig/intern/keyframing_auto.cc +++ b/source/blender/animrig/intern/keyframing_auto.cc @@ -353,7 +353,7 @@ bool autokeyframe_property(bContext *C, ReportList *reports = CTX_wm_reports(C); ToolSettings *ts = scene->toolsettings; const eInsertKeyFlags flag = get_autokey_flags(scene); - char *path = RNA_path_from_ID_to_property(ptr, prop); + const std::optional path = RNA_path_from_ID_to_property(ptr, prop); if (only_if_property_keyed) { /* NOTE: We use rnaindex instead of fcu->array_index, @@ -366,14 +366,12 @@ bool autokeyframe_property(bContext *C, id, action, (fcu && fcu->grp) ? fcu->grp->name : nullptr, - fcu ? fcu->rna_path : path, + fcu ? fcu->rna_path : (path ? path->c_str() : nullptr), rnaindex, &anim_eval_context, eBezTriple_KeyframeType(ts->keyframe_type), flag) != 0; - if (path) { - MEM_freeN(path); - } + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr); } } diff --git a/source/blender/blenkernel/BKE_key.hh b/source/blender/blenkernel/BKE_key.hh index cad8f52147d..7c6c4378c28 100644 --- a/source/blender/blenkernel/BKE_key.hh +++ b/source/blender/blenkernel/BKE_key.hh @@ -3,6 +3,9 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include +#include + /** \file * \ingroup bke */ @@ -101,7 +104,7 @@ void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src); * Get RNA-Path for 'value' setting of the given shape-key. * \note the user needs to free the returned string once they're finished with it. */ -char *BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb); +std::optional BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb); /* conversion functions */ /* NOTE: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */ diff --git a/source/blender/blenkernel/intern/action.cc b/source/blender/blenkernel/intern/action.cc index 1dfb1120796..232be615bb4 100644 --- a/source/blender/blenkernel/intern/action.cc +++ b/source/blender/blenkernel/intern/action.cc @@ -1480,7 +1480,6 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act, ListBase *curves) { PointerRNA ptr; - char *basePath = nullptr; short flags = 0; /* build PointerRNA from provided data to obtain the paths to use */ @@ -1495,8 +1494,8 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act, } /* get the basic path to the properties of interest */ - basePath = RNA_path_from_ID_to_struct(&ptr); - if (basePath == nullptr) { + const std::optional basePath = RNA_path_from_ID_to_struct(&ptr); + if (!basePath) { return eAction_TransformFlags(0); } @@ -1518,13 +1517,13 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act, } /* step 1: check for matching base path */ - bPtr = strstr(fcu->rna_path, basePath); + bPtr = strstr(fcu->rna_path, basePath->c_str()); if (bPtr) { /* we must add len(basePath) bytes to the match so that we are at the end of the * base path so that we don't get false positives with these strings in the names */ - bPtr += strlen(basePath); + bPtr += strlen(basePath->c_str()); /* step 2: check for some property with transforms * - to speed things up, only check for the ones not yet found @@ -1597,9 +1596,6 @@ eAction_TransformFlags BKE_action_get_item_transform_flags(bAction *act, } } - /* free basePath */ - MEM_freeN(basePath); - /* return flags found */ return eAction_TransformFlags(flags); } diff --git a/source/blender/blenkernel/intern/fcurve.cc b/source/blender/blenkernel/intern/fcurve.cc index d016035b102..9ea32d81895 100644 --- a/source/blender/blenkernel/intern/fcurve.cc +++ b/source/blender/blenkernel/intern/fcurve.cc @@ -238,15 +238,16 @@ FCurve *id_data_find_fcurve( return nullptr; } - char *path = RNA_path_from_ID_to_property(&ptr, prop); - if (path == nullptr) { + const std::optional path = RNA_path_from_ID_to_property(&ptr, prop); + if (!path) { return nullptr; } /* FIXME: The way drivers are handled here (always nullptr-ifying `fcu`) is very weird, this * needs to be re-checked I think?. */ bool is_driven = false; - FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, nullptr, &is_driven); + FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path( + adt, path->c_str(), index, nullptr, &is_driven); if (is_driven) { if (r_driven != nullptr) { *r_driven = is_driven; @@ -254,8 +255,6 @@ FCurve *id_data_find_fcurve( fcu = nullptr; } - MEM_freeN(path); - return fcu; } @@ -454,19 +453,19 @@ FCurve *BKE_fcurve_find_by_rna_context_ui(bContext * /*C*/, } /* XXX This function call can become a performance bottleneck. */ - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path == nullptr) { + const std::optional rna_path = RNA_path_from_ID_to_property(ptr, prop); + if (!rna_path) { return nullptr; } /* Standard F-Curve from animdata - Animation (Action) or Drivers. */ - FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, rna_path, rnaindex, r_action, r_driven); + FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path( + adt, rna_path->c_str(), rnaindex, r_action, r_driven); if (fcu != nullptr && r_animdata != nullptr) { *r_animdata = adt; } - MEM_freeN(rna_path); return fcu; } diff --git a/source/blender/blenkernel/intern/key.cc b/source/blender/blenkernel/intern/key.cc index ca501dc9eaa..61df48879eb 100644 --- a/source/blender/blenkernel/intern/key.cc +++ b/source/blender/blenkernel/intern/key.cc @@ -1946,21 +1946,13 @@ void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src) kb_dst->slidermax = kb_src->slidermax; } -char *BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb) +std::optional BKE_keyblock_curval_rnapath_get(const Key *key, const KeyBlock *kb) { - PropertyRNA *prop; - - /* sanity checks */ if (ELEM(nullptr, key, kb)) { return nullptr; } - - /* create the RNA pointer */ PointerRNA ptr = RNA_pointer_create((ID *)&key->id, &RNA_ShapeKey, (KeyBlock *)kb); - /* get pointer to the property too */ - prop = RNA_struct_find_property(&ptr, "value"); - - /* return the path */ + PropertyRNA *prop = RNA_struct_find_property(&ptr, "value"); return RNA_path_from_ID_to_property(&ptr, prop); } diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 44efdcbd2ab..381c5c1e30a 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -254,15 +254,14 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph, * given the COW ID pointer as the new lookup point */ /* TODO: Find a faster alternative, or implement support for other * common types too above (e.g. modifiers) */ - char *path = RNA_path_from_ID_to_struct(ptr); - if (path) { + if (const std::optional path = RNA_path_from_ID_to_struct(ptr)) { PointerRNA cow_id_ptr = RNA_id_pointer_create(cow_id); - if (!RNA_path_resolve(&cow_id_ptr, path, r_ptr_eval, nullptr)) { + if (!RNA_path_resolve(&cow_id_ptr, path->c_str(), r_ptr_eval, nullptr)) { /* Couldn't find COW copy of data */ fprintf(stderr, "%s: Couldn't resolve RNA path ('%s') relative to COW ID (%p) for '%s'\n", __func__, - path, + path->c_str(), (void *)cow_id, orig_id->name); } diff --git a/source/blender/editors/animation/anim_channels_defines.cc b/source/blender/editors/animation/anim_channels_defines.cc index 44b10a6b83c..8ff3c605034 100644 --- a/source/blender/editors/animation/anim_channels_defines.cc +++ b/source/blender/editors/animation/anim_channels_defines.cc @@ -5080,7 +5080,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi Main *bmain = CTX_data_main(C); Key *key = (Key *)key_poin; KeyBlock *kb = (KeyBlock *)kb_poin; - char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb); + std::optional rna_path = BKE_keyblock_curval_rnapath_get(key, kb); ReportList *reports = CTX_wm_reports(C); Scene *scene = CTX_data_scene(C); @@ -5109,11 +5109,12 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi flag = ANIM_get_keyframing_flags(scene); /* try to resolve the path stored in the F-Curve */ - if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) { + if (RNA_path_resolve_property(&id_ptr, rna_path ? rna_path->c_str() : nullptr, &ptr, &prop)) { /* find or create new F-Curve */ /* XXX is the group name for this ok? */ bAction *act = blender::animrig::id_action_ensure(bmain, (ID *)key); - FCurve *fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, &ptr, rna_path, 0); + FCurve *fcu = blender::animrig::action_fcurve_ensure( + bmain, act, nullptr, &ptr, rna_path->c_str(), 0); /* set the special 'replace' flag if on a keyframe */ if (fcurve_frame_has_keyframe(fcu, remapped_frame)) { @@ -5137,11 +5138,6 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi } } - /* free the path */ - if (rna_path) { - MEM_freeN(rna_path); - } - BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); } @@ -5478,8 +5474,11 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale, UI_block_emboss_set(block, UI_EMBOSS_NONE); PropertyRNA *onion_skinning_prop = RNA_struct_find_property(&ptr, "use_onion_skinning"); - char *onion_skinning_rna_path = RNA_path_from_ID_to_property(&ptr, onion_skinning_prop); - if (RNA_path_resolve_property(&id_ptr, onion_skinning_rna_path, &ptr, &onion_skinning_prop)) { + const std::optional onion_skinning_rna_path = RNA_path_from_ID_to_property( + &ptr, onion_skinning_prop); + if (RNA_path_resolve_property( + &id_ptr, onion_skinning_rna_path->c_str(), &ptr, &onion_skinning_prop)) + { const int icon = layer->use_onion_skinning() ? ICON_ONIONSKIN_ON : ICON_ONIONSKIN_OFF; uiDefAutoButR(block, &ptr, @@ -5492,15 +5491,15 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale, ICON_WIDTH, channel_height); } - MEM_freeN(onion_skinning_rna_path); /* Layer opacity. */ const short width = SLIDER_WIDTH * 0.6; offset -= width; UI_block_emboss_set(block, UI_EMBOSS); PropertyRNA *opacity_prop = RNA_struct_find_property(&ptr, "opacity"); - char *opacity_rna_path = RNA_path_from_ID_to_property(&ptr, opacity_prop); - if (RNA_path_resolve_property(&id_ptr, opacity_rna_path, &ptr, &opacity_prop)) { + const std::optional opacity_rna_path = RNA_path_from_ID_to_property(&ptr, + opacity_prop); + if (RNA_path_resolve_property(&id_ptr, opacity_rna_path->c_str(), &ptr, &opacity_prop)) { uiDefAutoButR(block, &ptr, opacity_prop, @@ -5512,7 +5511,6 @@ static void draw_grease_pencil_layer_widgets(bAnimListElem *ale, width, channel_height); } - MEM_freeN(opacity_rna_path); } #endif @@ -5836,9 +5834,8 @@ void ANIM_channel_draw_widgets(const bContext *C, else if (ale->id) { /* Slider using RNA Access --------------- */ PointerRNA ptr; PropertyRNA *prop; - char *rna_path = nullptr; + std::optional rna_path; int array_index = 0; - short free_path = 0; /* get destination info */ if (ale->type == ANIMTYPE_FCURVE) { @@ -5852,7 +5849,6 @@ void ANIM_channel_draw_widgets(const bContext *C, Key *key = (Key *)ale->id; rna_path = BKE_keyblock_curval_rnapath_get(key, kb); - free_path = 1; } /* Special for Grease Pencil Layer. */ else if (ale->type == ANIMTYPE_GPLAYER) { @@ -5861,7 +5857,6 @@ void ANIM_channel_draw_widgets(const bContext *C, /* Reset slider offset, in order to add special gp icons. */ offset += SLIDER_WIDTH; - char *gp_rna_path = nullptr; bGPDlayer *gpl = (bGPDlayer *)ale->data; /* Create the RNA pointers. */ @@ -5873,67 +5868,73 @@ void ANIM_channel_draw_widgets(const bContext *C, offset -= ICON_WIDTH; UI_block_emboss_set(block, UI_EMBOSS_NONE); prop = RNA_struct_find_property(&ptr, "use_onion_skinning"); - gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop); - if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) { - icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON : - ICON_ONIONSKIN_OFF; - uiDefAutoButR(block, - &ptr, - prop, - array_index, - "", - icon, - offset, - rect->ymin, - ICON_WIDTH, - channel_height); + if (const std::optional gp_rna_path = RNA_path_from_ID_to_property(&ptr, + prop)) + { + if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) { + icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON : + ICON_ONIONSKIN_OFF; + uiDefAutoButR(block, + &ptr, + prop, + array_index, + "", + icon, + offset, + rect->ymin, + ICON_WIDTH, + channel_height); + } } - MEM_freeN(gp_rna_path); /* Mask Layer. */ offset -= ICON_WIDTH; UI_block_emboss_set(block, UI_EMBOSS_NONE); prop = RNA_struct_find_property(&ptr, "use_mask_layer"); - gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop); - if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) { - if (gpl->flag & GP_LAYER_USE_MASK) { - icon = ICON_MOD_MASK; + if (const std::optional gp_rna_path = RNA_path_from_ID_to_property(&ptr, + prop)) + { + if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) { + if (gpl->flag & GP_LAYER_USE_MASK) { + icon = ICON_MOD_MASK; + } + else { + icon = ICON_LAYER_ACTIVE; + } + uiDefAutoButR(block, + &ptr, + prop, + array_index, + "", + icon, + offset, + rect->ymin, + ICON_WIDTH, + channel_height); } - else { - icon = ICON_LAYER_ACTIVE; - } - uiDefAutoButR(block, - &ptr, - prop, - array_index, - "", - icon, - offset, - rect->ymin, - ICON_WIDTH, - channel_height); } - MEM_freeN(gp_rna_path); /* Layer opacity. */ const short width = SLIDER_WIDTH * 0.6; offset -= width; UI_block_emboss_set(block, UI_EMBOSS); prop = RNA_struct_find_property(&ptr, "opacity"); - gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop); - if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) { - uiDefAutoButR(block, - &ptr, - prop, - array_index, - "", - ICON_NONE, - offset, - rect->ymin, - width, - channel_height); + if (const std::optional gp_rna_path = RNA_path_from_ID_to_property(&ptr, + prop)) + { + if (RNA_path_resolve_property(&id_ptr, gp_rna_path->c_str(), &ptr, &prop)) { + uiDefAutoButR(block, + &ptr, + prop, + array_index, + "", + ICON_NONE, + offset, + rect->ymin, + width, + channel_height); + } } - MEM_freeN(gp_rna_path); } } #ifdef WITH_GREASE_PENCIL_V3 @@ -5948,7 +5949,9 @@ void ANIM_channel_draw_widgets(const bContext *C, PointerRNA id_ptr = RNA_id_pointer_create(ale->id); /* try to resolve the path */ - if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) { + if (RNA_path_resolve_property( + &id_ptr, rna_path ? rna_path->c_str() : nullptr, &ptr, &prop)) + { uiBut *but; /* Create the slider button, @@ -5972,11 +5975,6 @@ void ANIM_channel_draw_widgets(const bContext *C, UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data); } } - - /* free the path if necessary */ - if (free_path) { - MEM_freeN(rna_path); - } } } else { /* Special Slider for stuff without RNA Access ---------- */ diff --git a/source/blender/editors/animation/anim_channels_edit.cc b/source/blender/editors/animation/anim_channels_edit.cc index c95f67506ea..ddb3617f4a9 100644 --- a/source/blender/editors/animation/anim_channels_edit.cc +++ b/source/blender/editors/animation/anim_channels_edit.cc @@ -4533,7 +4533,7 @@ static rctf calculate_selection_fcurve_bounds_and_unhide( bContext *C, ListBase /* CollectionPointerLink */ *selection, PropertyRNA *prop, - char *id_to_prop_path, + const blender::StringRefNull id_to_prop_path, const int index, const bool whole_array) { @@ -4560,9 +4560,9 @@ static rctf calculate_selection_fcurve_bounds_and_unhide( } PointerRNA resolved_ptr; PropertyRNA *resolved_prop; - if (id_to_prop_path != nullptr) { + if (!id_to_prop_path.is_empty()) { const bool resolved = RNA_path_resolve_property( - &selected->ptr, id_to_prop_path, &resolved_ptr, &resolved_prop); + &selected->ptr, id_to_prop_path.c_str(), &resolved_ptr, &resolved_prop); if (!resolved) { continue; } @@ -4571,7 +4571,8 @@ static rctf calculate_selection_fcurve_bounds_and_unhide( resolved_ptr = selected->ptr; resolved_prop = prop; } - char *path = RNA_path_from_ID_to_property(&resolved_ptr, resolved_prop); + const std::optional path = RNA_path_from_ID_to_property(&resolved_ptr, + resolved_prop); AnimData *anim_data = BKE_animdata_from_id(selected_id); blender::Vector fcurves; @@ -4579,7 +4580,7 @@ static rctf calculate_selection_fcurve_bounds_and_unhide( const int length = RNA_property_array_length(&selected->ptr, prop); for (int i = 0; i < length; i++) { FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path( - anim_data, path, i, nullptr, nullptr); + anim_data, path->c_str(), i, nullptr, nullptr); if (fcurve != nullptr) { fcurves.append(fcurve); } @@ -4587,14 +4588,12 @@ static rctf calculate_selection_fcurve_bounds_and_unhide( } else { FCurve *fcurve = BKE_animadata_fcurve_find_by_rna_path( - anim_data, path, index, nullptr, nullptr); + anim_data, path->c_str(), index, nullptr, nullptr); if (fcurve != nullptr) { fcurves.append(fcurve); } } - MEM_freeN(path); - for (FCurve *fcurve : fcurves) { fcurve->flag |= (FCURVE_SELECTED | FCURVE_VISIBLE); rctf fcu_bounds; @@ -4633,7 +4632,7 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op) ListBase selection = {nullptr, nullptr}; bool path_from_id; - char *id_to_prop_path; + std::optional id_to_prop_path; const bool selected_list_success = UI_context_copy_to_selected_list( C, &ptr, prop, &selection, &path_from_id, &id_to_prop_path); @@ -4663,14 +4662,10 @@ static int view_curve_in_graph_editor_exec(bContext *C, wmOperator *op) const bool whole_array = RNA_boolean_get(op->ptr, "all"); rctf bounds = calculate_selection_fcurve_bounds_and_unhide( - C, &selection, prop, id_to_prop_path, index, whole_array); + C, &selection, prop, id_to_prop_path.value_or(""), index, whole_array); BLI_freelistN(&selection); - if (id_to_prop_path != nullptr) { - MEM_freeN(id_to_prop_path); - } - if (!BLI_rctf_is_valid(&bounds)) { WM_report(RPT_ERROR, "F-Curves have no valid size"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/animation/anim_filter.cc b/source/blender/editors/animation/anim_filter.cc index 356d2654c34..46c6c653183 100644 --- a/source/blender/editors/animation/anim_filter.cc +++ b/source/blender/editors/animation/anim_filter.cc @@ -942,14 +942,9 @@ static bAnimListElem *make_new_animlistelem(void *data, /* the corresponding keyframes are from the animdata */ if (ale->adt && ale->adt->action) { bAction *act = ale->adt->action; - char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb); - - /* try to find the F-Curve which corresponds to this exactly, - * then free the MEM_alloc'd string - */ - if (rna_path) { - ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path, 0); - MEM_freeN(rna_path); + /* Try to find the F-Curve which corresponds to this exactly. */ + if (std::optional rna_path = BKE_keyblock_curval_rnapath_get(key, kb)) { + ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path->c_str(), 0); } } ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE; diff --git a/source/blender/editors/animation/drivers.cc b/source/blender/editors/animation/drivers.cc index 38b72ef6398..f31192b8f3e 100644 --- a/source/blender/editors/animation/drivers.cc +++ b/source/blender/editors/animation/drivers.cc @@ -953,13 +953,11 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ } if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = RNA_path_from_ID_to_property(&ptr, prop); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { success += ANIM_add_driver( - op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON); - MEM_freeN(path); + op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON); } } @@ -1047,14 +1045,13 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent * if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { /* 1) Create a new "empty" driver for this property */ - char *path = RNA_path_from_ID_to_property(&ptr, prop); short flags = CREATEDRIVER_WITH_DEFAULT_DVAR; bool changed = false; - if (path) { - changed |= (ANIM_add_driver( - op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON) != 0); - MEM_freeN(path); + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { + changed |= + (ANIM_add_driver( + op->reports, ptr.owner_id, path->c_str(), index, flags, DRIVER_TYPE_PYTHON) != 0); } if (changed) { @@ -1106,12 +1103,8 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op) } if (ptr.owner_id && ptr.data && prop) { - char *path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - changed = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0); - - MEM_freeN(path); + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { + changed = ANIM_remove_driver(op->reports, ptr.owner_id, path->c_str(), index, 0); } } @@ -1189,15 +1182,11 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op) UI_context_active_but_prop_get(C, &ptr, &prop, &index); if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { /* only copy the driver for the button that this was involved for */ - changed = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0); + changed = ANIM_copy_driver(op->reports, ptr.owner_id, path->c_str(), index, 0); UI_context_update_anim_flag(C); - - MEM_freeN(path); } } @@ -1232,11 +1221,9 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) UI_context_active_but_prop_get(C, &ptr, &prop, &index); if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - char *path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { /* only copy the driver for the button that this was involved for */ - changed = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0); + changed = ANIM_paste_driver(op->reports, ptr.owner_id, path->c_str(), index, 0); UI_context_update_anim_flag(C); @@ -1245,8 +1232,6 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op) DEG_id_tag_update(ptr.owner_id, ID_RECALC_ANIMATION); WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, nullptr); /* XXX */ - - MEM_freeN(path); } } diff --git a/source/blender/editors/animation/keyframing.cc b/source/blender/editors/animation/keyframing.cc index e5dba978297..61c260424d0 100644 --- a/source/blender/editors/animation/keyframing.cc +++ b/source/blender/editors/animation/keyframing.cc @@ -870,7 +870,6 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) ToolSettings *ts = scene->toolsettings; PointerRNA ptr = {nullptr}; PropertyRNA *prop = nullptr; - char *path; uiBut *but; const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct( CTX_data_depsgraph_pointer(C), BKE_scene_frame_get(scene)); @@ -938,9 +937,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) } else { /* standard properties */ - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { const char *identifier = RNA_property_identifier(prop); const char *group = nullptr; @@ -975,13 +972,11 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) ptr.owner_id, nullptr, group, - path, + path->c_str(), index, &anim_eval_context, eBezTriple_KeyframeType(ts->keyframe_type), flag) != 0); - - MEM_freeN(path); } else { BKE_report(op->reports, @@ -1052,7 +1047,6 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) PointerRNA ptr = {nullptr}; PropertyRNA *prop = nullptr; Main *bmain = CTX_data_main(C); - char *path; const float cfra = BKE_scene_frame_get(scene); bool changed = false; int index; @@ -1104,17 +1098,14 @@ static int delete_key_button_exec(bContext *C, wmOperator *op) } else { /* standard properties */ - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { if (all) { /* -1 indicates operating on the entire array (or the property itself otherwise) */ index = -1; } changed = blender::animrig::delete_keyframe( - bmain, op->reports, ptr.owner_id, nullptr, path, index, cfra) != 0; - MEM_freeN(path); + bmain, op->reports, ptr.owner_id, nullptr, path->c_str(), index, cfra) != 0; } else if (G.debug & G_DEBUG) { printf("Button Delete-Key: no path to property\n"); @@ -1161,7 +1152,6 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) PointerRNA ptr = {nullptr}; PropertyRNA *prop = nullptr; Main *bmain = CTX_data_main(C); - char *path; bool changed = false; int index; const bool all = RNA_boolean_get(op->ptr, "all"); @@ -1172,18 +1162,19 @@ static int clear_key_button_exec(bContext *C, wmOperator *op) } if (ptr.owner_id && ptr.data && prop) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { if (all) { /* -1 indicates operating on the entire array (or the property itself otherwise) */ index = -1; } - changed |= - (blender::animrig::clear_keyframe( - bmain, op->reports, ptr.owner_id, nullptr, path, index, eInsertKeyFlags(0)) != 0); - MEM_freeN(path); + changed |= (blender::animrig::clear_keyframe(bmain, + op->reports, + ptr.owner_id, + nullptr, + path->c_str(), + index, + eInsertKeyFlags(0)) != 0); } else if (G.debug & G_DEBUG) { printf("Button Clear-Key: no path to property\n"); diff --git a/source/blender/editors/animation/keyingsets.cc b/source/blender/editors/animation/keyingsets.cc index ccb0dcc09ff..eb5b9c8b960 100644 --- a/source/blender/editors/animation/keyingsets.cc +++ b/source/blender/editors/animation/keyingsets.cc @@ -304,12 +304,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) /* Check if property is able to be added. */ const bool all = RNA_boolean_get(op->ptr, "all"); - char *path = nullptr; bool changed = false; if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { if (all) { pflag |= KSP_FLAG_WHOLE_ARRAY; @@ -322,11 +319,9 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op) /* Add path to this setting. */ BKE_keyingset_add_path( - keyingset, ptr.owner_id, nullptr, path, index, pflag, KSP_GROUP_KSNAME); + keyingset, ptr.owner_id, nullptr, path->c_str(), index, pflag, KSP_GROUP_KSNAME); keyingset->active_path = BLI_listbase_count(&keyingset->paths); changed = true; - - MEM_freeN(path); } } @@ -390,21 +385,16 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op) BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1)); bool changed = false; - char *path = nullptr; if (ptr.owner_id && ptr.data && prop) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { /* Try to find a path matching this description. */ KS_Path *keyingset_path = BKE_keyingset_find_path( - keyingset, ptr.owner_id, keyingset->name, path, index, KSP_GROUP_KSNAME); + keyingset, ptr.owner_id, keyingset->name, path->c_str(), index, KSP_GROUP_KSNAME); if (keyingset_path) { BKE_keyingset_free_path(keyingset, keyingset_path); changed = true; } - - MEM_freeN(path); } } diff --git a/source/blender/editors/armature/pose_utils.cc b/source/blender/editors/armature/pose_utils.cc index 416e6ccdec4..c4fe0d4c50e 100644 --- a/source/blender/editors/armature/pose_utils.cc +++ b/source/blender/editors/armature/pose_utils.cc @@ -76,7 +76,7 @@ static void fcurves_to_pchan_links_get(ListBase *pfLinks, /* get the RNA path to this pchan - this needs to be freed! */ PointerRNA ptr = RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan); - pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr); + pfl->pchan_path = BLI_strdup(RNA_path_from_ID_to_struct(&ptr).value_or("").c_str()); /* add linkage data to operator data */ BLI_addtail(pfLinks, pfl); diff --git a/source/blender/editors/include/UI_interface_c.hh b/source/blender/editors/include/UI_interface_c.hh index f70dd0e6945..b6b5a2bba10 100644 --- a/source/blender/editors/include/UI_interface_c.hh +++ b/source/blender/editors/include/UI_interface_c.hh @@ -3102,7 +3102,7 @@ bool UI_context_copy_to_selected_list(bContext *C, PropertyRNA *prop, ListBase *r_lb, bool *r_use_path_from_id, - char **r_path); + std::optional *r_path); bool UI_context_copy_to_selected_check(PointerRNA *ptr, PointerRNA *ptr_link, PropertyRNA *prop, diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc b/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc index 8a1c64a41e4..f4127fe2c24 100644 --- a/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc +++ b/source/blender/editors/interface/eyedroppers/eyedropper_driver.cc @@ -91,19 +91,20 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve PropertyRNA *target_prop = but->rnaprop; const int target_index = but->rnaindex; - char *target_path = RNA_path_from_ID_to_property(target_ptr, target_prop); + const std::optional target_path = RNA_path_from_ID_to_property(target_ptr, + target_prop); /* Get paths for the destination. */ - char *dst_path = RNA_path_from_ID_to_property(&ddr->ptr, ddr->prop); + const std::optional dst_path = RNA_path_from_ID_to_property(&ddr->ptr, ddr->prop); /* Now create driver(s) */ if (target_path && dst_path) { int success = ANIM_add_driver_with_target(op->reports, ddr->ptr.owner_id, - dst_path, + dst_path->c_str(), ddr->index, target_ptr->owner_id, - target_path, + target_path->c_str(), target_index, flag, DRIVER_TYPE_PYTHON, @@ -117,14 +118,6 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, nullptr); /* XXX */ } } - - /* cleanup */ - if (target_path) { - MEM_freeN(target_path); - } - if (dst_path) { - MEM_freeN(dst_path); - } } static void driverdropper_cancel(bContext *C, wmOperator *op) diff --git a/source/blender/editors/interface/interface_anim.cc b/source/blender/editors/interface/interface_anim.cc index b1b50fd7e6a..1c8eb8b0fb7 100644 --- a/source/blender/editors/interface/interface_anim.cc +++ b/source/blender/editors/interface/interface_anim.cc @@ -237,7 +237,6 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) bContext *C = static_cast(but->block->evil_C); ID *id; FCurve *fcu; - char *path; bool ok = false; /* button must have RNA-pointer to a numeric-capable property */ @@ -269,13 +268,14 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) } /* get path */ - path = RNA_path_from_ID_to_property(&but->rnapoin, but->rnaprop); - if (path == nullptr) { + const std::optional path = RNA_path_from_ID_to_property(&but->rnapoin, + but->rnaprop); + if (!path) { return false; } /* create driver */ - fcu = verify_driver_fcurve(id, path, but->rnaindex, DRIVER_FCURVE_KEYFRAMES); + fcu = verify_driver_fcurve(id, path->c_str(), but->rnaindex, DRIVER_FCURVE_KEYFRAMES); if (fcu) { ChannelDriver *driver = fcu->driver; @@ -295,8 +295,6 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str) } } - MEM_freeN(path); - return ok; } diff --git a/source/blender/editors/interface/interface_context_menu.cc b/source/blender/editors/interface/interface_context_menu.cc index 4258cb11c31..80acd1798e2 100644 --- a/source/blender/editors/interface/interface_context_menu.cc +++ b/source/blender/editors/interface/interface_context_menu.cc @@ -354,11 +354,11 @@ static bUserMenuItem *ui_but_user_menu_find(bContext *C, uiBut *but, bUserMenu * return nullptr; } /* Ignore the actual array index [pass -1] since the index is handled separately. */ - const char *prop_id = RNA_property_is_idprop(but->rnaprop) ? - RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) : - RNA_property_identifier(but->rnaprop); + const std::string prop_id = RNA_property_is_idprop(but->rnaprop) ? + RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) : + RNA_property_identifier(but->rnaprop); bUserMenuItem *umi = (bUserMenuItem *)ED_screen_user_menu_item_find_prop( - &um->items, member_id_data_path.value().c_str(), prop_id, but->rnaindex); + &um->items, member_id_data_path->c_str(), prop_id.c_str(), but->rnaindex); return umi; } @@ -436,12 +436,12 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) } else { /* Ignore the actual array index [pass -1] since the index is handled separately. */ - const char *prop_id = RNA_property_is_idprop(but->rnaprop) ? - RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) : - RNA_property_identifier(but->rnaprop); + const std::string prop_id = RNA_property_is_idprop(but->rnaprop) ? + RNA_path_property_py(&but->rnapoin, but->rnaprop, -1) : + RNA_property_identifier(but->rnaprop); /* NOTE: ignore 'drawstr', use property idname always. */ ED_screen_user_menu_item_add_prop( - &um->items, "", member_id_data_path.value().c_str(), prop_id, but->rnaindex); + &um->items, "", member_id_data_path->c_str(), prop_id.c_str(), but->rnaindex); } } else if ((mt = UI_but_menutype_get(but))) { diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 4cf9ec14a02..9b028cb56e9 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -1824,7 +1824,6 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore PropertyRNA *lprop; bool success = false; - char *path = nullptr; ListBase lb = {nullptr}; PointerRNA ptr = but->rnapoin; @@ -1844,6 +1843,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore const bool is_array = RNA_property_array_check(prop); const int rna_type = RNA_property_type(prop); + std::optional path; if (UI_context_copy_to_selected_list(C, &ptr, prop, &lb, &use_path_from_id, &path) && !BLI_listbase_is_empty(&lb)) { @@ -1856,8 +1856,13 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore break; } - if (!UI_context_copy_to_selected_check( - &ptr, &link->ptr, prop, path, use_path_from_id, &lptr, &lprop)) + if (!UI_context_copy_to_selected_check(&ptr, + &link->ptr, + prop, + path.has_value() ? path->c_str() : nullptr, + use_path_from_id, + &lptr, + &lprop)) { selctx_data->elems_len -= 1; i -= 1; @@ -1906,7 +1911,6 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore MEM_SAFE_FREE(selctx_data->elems); } - MEM_SAFE_FREE(path); BLI_freelistN(&lb); /* caller can clear */ diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc index 8f2ff6d4068..a5b14e8df50 100644 --- a/source/blender/editors/interface/interface_ops.cc +++ b/source/blender/editors/interface/interface_ops.cc @@ -8,6 +8,8 @@ #include +#include + #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" @@ -105,16 +107,12 @@ static bool copy_data_path_button_poll(bContext *C) { PointerRNA ptr; PropertyRNA *prop; - char *path; int index; UI_context_active_but_prop_get(C, &ptr, &prop, &index); if (ptr.owner_id && ptr.data && prop) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - MEM_freeN(path); + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { return true; } } @@ -127,7 +125,6 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op) Main *bmain = CTX_data_main(C); PointerRNA ptr; PropertyRNA *prop; - char *path; int index; ID *id; @@ -136,6 +133,7 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op) /* try to create driver using property retrieved from UI */ UI_context_active_but_prop_get(C, &ptr, &prop, &index); + std::optional path; if (ptr.owner_id != nullptr) { if (full_path) { if (prop) { @@ -155,8 +153,7 @@ static int copy_data_path_button_exec(bContext *C, wmOperator *op) } if (path) { - WM_clipboard_text_set(path, false); - MEM_freeN(path); + WM_clipboard_text_set(path->c_str(), false); return OPERATOR_FINISHED; } } @@ -195,7 +192,6 @@ static bool copy_as_driver_button_poll(bContext *C) { PointerRNA ptr; PropertyRNA *prop; - char *path; int index; UI_context_active_but_prop_get(C, &ptr, &prop, &index); @@ -204,10 +200,7 @@ static bool copy_as_driver_button_poll(bContext *C) ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM) && (index >= 0 || !RNA_property_array_check(prop))) { - path = RNA_path_from_ID_to_property(&ptr, prop); - - if (path) { - MEM_freeN(path); + if (const std::optional path = RNA_path_from_ID_to_property(&ptr, prop)) { return true; } } @@ -228,11 +221,10 @@ static int copy_as_driver_button_exec(bContext *C, wmOperator *op) if (ptr.owner_id && ptr.data && prop) { ID *id; const int dim = RNA_property_array_dimension(&ptr, prop, nullptr); - char *path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, dim, index, &id); - - if (path) { - ANIM_copy_as_driver(id, path, RNA_property_identifier(prop)); - MEM_freeN(path); + if (const std::optional path = RNA_path_from_real_ID_to_property_index( + bmain, &ptr, prop, dim, index, &id)) + { + ANIM_copy_as_driver(id, path->c_str(), RNA_property_identifier(prop)); return OPERATOR_FINISHED; } @@ -1077,12 +1069,11 @@ bool UI_context_copy_to_selected_list(bContext *C, PropertyRNA *prop, ListBase *r_lb, bool *r_use_path_from_id, - char **r_path) + std::optional *r_path) { *r_use_path_from_id = false; - *r_path = nullptr; + *r_path = std::nullopt; /* special case for bone constraints */ - char *path_from_bone = nullptr; const bool is_rna = !RNA_property_is_idprop(prop); /* Remove links from the collection list which don't contain 'prop'. */ bool ensure_list_items_contain_prop = false; @@ -1097,34 +1088,34 @@ bool UI_context_copy_to_selected_list(bContext *C, */ if (is_rna && RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) { PointerRNA owner_ptr; - char *idpath = nullptr; + std::optional idpath; /* First, check the active PoseBone and PoseBone->Bone. */ if (NOT_RNA_NULL(owner_ptr = CTX_data_pointer_get_type(C, "active_pose_bone", &RNA_PoseBone))) { - if (NOT_NULL(idpath = RNA_path_from_struct_to_idproperty( - &owner_ptr, static_cast(ptr->data)))) - { + idpath = RNA_path_from_struct_to_idproperty(&owner_ptr, + static_cast(ptr->data)); + if (idpath) { *r_lb = CTX_data_collection_get(C, "selected_pose_bones"); } else { bPoseChannel *pchan = static_cast(owner_ptr.data); owner_ptr = RNA_pointer_create(owner_ptr.owner_id, &RNA_Bone, pchan->bone); - - if (NOT_NULL(idpath = RNA_path_from_struct_to_idproperty( - &owner_ptr, static_cast(ptr->data)))) - { + idpath = RNA_path_from_struct_to_idproperty(&owner_ptr, + static_cast(ptr->data)); + if (idpath) { ui_context_selected_bones_via_pose(C, r_lb); } } } - if (idpath == nullptr) { + if (!idpath) { /* Check the active EditBone if in edit mode. */ + idpath = RNA_path_from_struct_to_idproperty(&owner_ptr, + static_cast(ptr->data)); if (NOT_RNA_NULL( owner_ptr = CTX_data_pointer_get_type_silent(C, "active_bone", &RNA_EditBone)) && - NOT_NULL(idpath = RNA_path_from_struct_to_idproperty( - &owner_ptr, static_cast(ptr->data)))) + idpath) { *r_lb = CTX_data_collection_get(C, "selected_editable_bones"); } @@ -1133,8 +1124,7 @@ bool UI_context_copy_to_selected_list(bContext *C, } if (idpath) { - *r_path = BLI_sprintfN("%s.%s", idpath, RNA_property_identifier(prop)); - MEM_freeN(idpath); + *r_path = fmt::format("{}.{}", *idpath, RNA_property_identifier(prop)); return true; } } @@ -1221,16 +1211,16 @@ bool UI_context_copy_to_selected_list(bContext *C, else if (RNA_struct_is_a(ptr->type, &RNA_MovieTrackingTrack)) { *r_lb = CTX_data_collection_get(C, "selected_movieclip_tracks"); } - else if (RNA_struct_is_a(ptr->type, &RNA_Constraint) && - (path_from_bone = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone)) != - nullptr) + else if (const std::optional path_from_bone = + RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone); + RNA_struct_is_a(ptr->type, &RNA_Constraint) && path_from_bone) { *r_lb = CTX_data_collection_get(C, "selected_pose_bones"); *r_path = path_from_bone; } else if (RNA_struct_is_a(ptr->type, &RNA_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { ListBase lb = {nullptr, nullptr}; - char *path = nullptr; + std::optional path; bNode *node = nullptr; /* Get the node we're editing */ @@ -1238,7 +1228,8 @@ bool UI_context_copy_to_selected_list(bContext *C, bNodeTree *ntree = (bNodeTree *)ptr->owner_id; bNodeSocket *sock = static_cast(ptr->data); if (nodeFindNodeTry(ntree, sock, &node, nullptr)) { - if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != nullptr) { + path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node); + if (path) { /* we're good! */ } else { @@ -1279,7 +1270,7 @@ bool UI_context_copy_to_selected_list(bContext *C, /* check we're using the active object */ const short id_code = GS(id->name); ListBase lb = CTX_data_collection_get(C, "selected_editable_objects"); - char *path = RNA_path_from_ID_to_property(ptr, prop); + const std::optional path = RNA_path_from_ID_to_property(ptr, prop); /* de-duplicate obdata */ if (!BLI_listbase_is_empty(&lb)) { @@ -1319,8 +1310,8 @@ bool UI_context_copy_to_selected_list(bContext *C, /* Sequencer's ID is scene :/ */ /* Try to recursively find an RNA_Sequence ancestor, * to handle situations like #41062... */ - if ((*r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence)) != nullptr) - { + *r_path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Sequence); + if (r_path->has_value()) { /* Special case when we do this for 'Sequence.lock'. * (if the sequence is locked, it won't be in "selected_editable_sequences"). */ const char *prop_id = RNA_property_identifier(prop); @@ -1337,14 +1328,14 @@ bool UI_context_copy_to_selected_list(bContext *C, } } } - return (*r_path != nullptr); + return r_path->has_value(); } else { return false; } if (RNA_property_is_idprop(prop)) { - if (*r_path == nullptr) { + if (!r_path->has_value()) { *r_path = RNA_path_from_ptr_to_property_index(ptr, prop, 0, -1); BLI_assert(*r_path); } @@ -1371,7 +1362,8 @@ bool UI_context_copy_to_selected_list(bContext *C, LISTBASE_FOREACH_MUTABLE (CollectionPointerLink *, link, r_lb) { PointerRNA lptr; PropertyRNA *lprop = nullptr; - RNA_path_resolve_property(&link->ptr, *r_path, &lptr, &lprop); + RNA_path_resolve_property( + &link->ptr, r_path->has_value() ? r_path->value().c_str() : nullptr, &lptr, &lprop); bool remove = false; if (lprop == nullptr) { @@ -1517,7 +1509,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) } bool success = false; - char *path = nullptr; + std::optional path; bool use_path_from_id; ListBase lb = {nullptr}; @@ -1527,8 +1519,13 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) continue; } - if (!UI_context_copy_to_selected_check( - &ptr, &link->ptr, prop, path, use_path_from_id, &lptr, &lprop)) + if (!UI_context_copy_to_selected_check(&ptr, + &link->ptr, + prop, + path.has_value() ? path->c_str() : nullptr, + use_path_from_id, + &lptr, + &lprop)) { continue; } @@ -1544,7 +1541,6 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll) } } - MEM_SAFE_FREE(path); BLI_freelistN(&lb); return success; diff --git a/source/blender/editors/interface/interface_region_tooltip.cc b/source/blender/editors/interface/interface_region_tooltip.cc index 1089bc51cfb..48a45cca375 100644 --- a/source/blender/editors/interface/interface_region_tooltip.cc +++ b/source/blender/editors/interface/interface_region_tooltip.cc @@ -1042,11 +1042,10 @@ static uiTooltipData *ui_tooltip_data_from_button_or_extra_icon(bContext *C, } if (but->rnapoin.owner_id) { - char *str = rnaprop ? - RNA_path_full_property_py_ex(&but->rnapoin, rnaprop, but->rnaindex, true) : - RNA_path_full_struct_py(&but->rnapoin); - UI_tooltip_text_field_add(data, str, {}, UI_TIP_STYLE_MONO, UI_TIP_LC_PYTHON); - MEM_freeN(str); + std::optional str = rnaprop ? RNA_path_full_property_py_ex( + &but->rnapoin, rnaprop, but->rnaindex, true) : + RNA_path_full_struct_py(&but->rnapoin); + UI_tooltip_text_field_add(data, str.value_or(""), {}, UI_TIP_STYLE_MONO, UI_TIP_LC_PYTHON); } } diff --git a/source/blender/editors/object/object_constraint.cc b/source/blender/editors/object/object_constraint.cc index 2ed89875b3b..9be32e10d69 100644 --- a/source/blender/editors/object/object_constraint.cc +++ b/source/blender/editors/object/object_constraint.cc @@ -1089,28 +1089,22 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op) else { /* animate constraint's "fixed offset" */ PropertyRNA *prop; - char *path; /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */ PointerRNA ptr = RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con); prop = RNA_struct_find_property(&ptr, "offset_factor"); - path = RNA_path_from_ID_to_property(&ptr, prop); + const std::optional path = RNA_path_from_ID_to_property(&ptr, prop); /* create F-Curve for constraint */ act = blender::animrig::id_action_ensure(bmain, &ob->id); - fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, nullptr, path, 0); + fcu = blender::animrig::action_fcurve_ensure(bmain, act, nullptr, nullptr, path->c_str(), 0); /* standard vertical range - 0.0 to 1.0 */ standardRange = 1.0f; /* enable "Use Fixed Position" so that animating this has effect */ data->followflag |= FOLLOWPATH_STATIC; - - /* path needs to be freed */ - if (path) { - MEM_freeN(path); - } } /* setup dummy 'generator' modifier here to get 1-1 correspondence still working diff --git a/source/blender/editors/space_console/space_console.cc b/source/blender/editors/space_console/space_console.cc index 9bce3be7877..c327100d4a9 100644 --- a/source/blender/editors/space_console/space_console.cc +++ b/source/blender/editors/space_console/space_console.cc @@ -161,9 +161,8 @@ static void id_drop_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *drop) ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ - char *text = RNA_path_full_ID_py(id); - RNA_string_set(drop->ptr, "text", text); - MEM_freeN(text); + std::string text = RNA_path_full_ID_py(id); + RNA_string_set(drop->ptr, "text", text.c_str()); } static bool path_drop_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * /*event*/) diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index e5ae4217a94..727667b736c 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -221,13 +221,13 @@ void NODE_OT_group_edit(wmOperatorType *ot) * The given paths will be owned by the returned instance. * Both pointers are allowed to point to the same string. */ -static AnimationBasePathChange *animation_basepath_change_new(const char *src_basepath, - const char *dst_basepath) +static AnimationBasePathChange *animation_basepath_change_new(const StringRef src_basepath, + const StringRef dst_basepath) { AnimationBasePathChange *basepath_change = (AnimationBasePathChange *)MEM_callocN( sizeof(*basepath_change), AT); - basepath_change->src_basepath = src_basepath; - basepath_change->dst_basepath = dst_basepath; + basepath_change->src_basepath = BLI_strdupn(src_basepath.data(), src_basepath.size()); + basepath_change->dst_basepath = BLI_strdupn(dst_basepath.data(), dst_basepath.size()); return basepath_change; } @@ -295,7 +295,7 @@ static void node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) /* Keep track of this node's RNA "base" path (the part of the path identifying the node) * if the old node-tree has animation data which potentially covers this node. */ - const char *old_animation_basepath = nullptr; + std::optional old_animation_basepath; if (wgroup->adt) { PointerRNA ptr = RNA_pointer_create(&wgroup->id, &RNA_Node, node); old_animation_basepath = RNA_path_from_ID_to_struct(&ptr); @@ -313,9 +313,9 @@ static void node_group_ungroup(Main *bmain, bNodeTree *ntree, bNode *gnode) if (wgroup->adt) { PointerRNA ptr = RNA_pointer_create(&ntree->id, &RNA_Node, node); - const char *new_animation_basepath = RNA_path_from_ID_to_struct(&ptr); + const std::optional new_animation_basepath = RNA_path_from_ID_to_struct(&ptr); BLI_addtail(&anim_basepaths, - animation_basepath_change_new(old_animation_basepath, new_animation_basepath)); + animation_basepath_change_new(*old_animation_basepath, *new_animation_basepath)); } if (!node->parent) { @@ -538,13 +538,9 @@ static bool node_group_separate_selected( /* Keep track of this node's RNA "base" path (the part of the path identifying the node) * if the old node-tree has animation data which potentially covers this node. */ if (ngroup.adt) { - char *path; - PointerRNA ptr = RNA_pointer_create(&ngroup.id, &RNA_Node, newnode); - path = RNA_path_from_ID_to_struct(&ptr); - - if (path) { - BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path)); + if (const std::optional path = RNA_path_from_ID_to_struct(&ptr)) { + BLI_addtail(&anim_basepaths, animation_basepath_change_new(*path, *path)); } } @@ -1088,8 +1084,8 @@ static void node_group_make_insert_selected(const bContext &C, ListBase anim_basepaths = {nullptr, nullptr}; for (bNode *node : nodes_to_move) { PointerRNA ptr = RNA_pointer_create(&ntree.id, &RNA_Node, node); - if (char *path = RNA_path_from_ID_to_struct(&ptr)) { - BLI_addtail(&anim_basepaths, animation_basepath_change_new(path, path)); + if (const std::optional path = RNA_path_from_ID_to_struct(&ptr)) { + BLI_addtail(&anim_basepaths, animation_basepath_change_new(*path, *path)); } } BKE_animdata_transfer_by_basepath(bmain, &ntree.id, &group.id, &anim_basepaths); diff --git a/source/blender/editors/space_text/space_text.cc b/source/blender/editors/space_text/space_text.cc index caf723a59e6..833125afcc5 100644 --- a/source/blender/editors/space_text/space_text.cc +++ b/source/blender/editors/space_text/space_text.cc @@ -327,13 +327,11 @@ static bool text_drop_paste_poll(bContext * /*C*/, wmDrag *drag, const wmEvent * static void text_drop_paste(bContext * /*C*/, wmDrag *drag, wmDropBox *drop) { - char *text; ID *id = WM_drag_get_local_ID(drag, 0); /* copy drag path to properties */ - text = RNA_path_full_ID_py(id); - RNA_string_set(drop->ptr, "text", text); - MEM_freeN(text); + std::string text = RNA_path_full_ID_py(id); + RNA_string_set(drop->ptr, "text", text.c_str()); } /* this region dropbox definition */ diff --git a/source/blender/makesrna/RNA_access.hh b/source/blender/makesrna/RNA_access.hh index ffe5b22f17f..0c1ab85bd75 100644 --- a/source/blender/makesrna/RNA_access.hh +++ b/source/blender/makesrna/RNA_access.hh @@ -10,7 +10,9 @@ * \ingroup RNA */ +#include #include +#include #include "RNA_types.hh" @@ -636,34 +638,34 @@ void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier); /** * Python compatible string representation of this property, (must be freed!). */ -char *RNA_property_as_string( +std::string RNA_property_as_string( bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length); /** * String representation of a property, Python compatible but can be used for display too. * \param C: can be NULL. */ -char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr); -char *RNA_pointer_as_string(bContext *C, - PointerRNA *ptr, - PropertyRNA *prop_ptr, - PointerRNA *ptr_prop); +std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr); +std::optional RNA_pointer_as_string(bContext *C, + PointerRNA *ptr, + PropertyRNA *prop_ptr, + PointerRNA *ptr_prop); /** * \param C: can be NULL. */ -char *RNA_pointer_as_string_keywords_ex(bContext *C, - PointerRNA *ptr, - bool as_function, - bool all_args, - bool nested_args, - int max_prop_length, - PropertyRNA *iterprop); -char *RNA_pointer_as_string_keywords(bContext *C, - PointerRNA *ptr, - bool as_function, - bool all_args, - bool nested_args, - int max_prop_length); -char *RNA_function_as_string_keywords( +std::string RNA_pointer_as_string_keywords_ex(bContext *C, + PointerRNA *ptr, + bool as_function, + bool all_args, + bool nested_args, + int max_prop_length, + PropertyRNA *iterprop); +std::string RNA_pointer_as_string_keywords(bContext *C, + PointerRNA *ptr, + bool as_function, + bool all_args, + bool nested_args, + int max_prop_length); +std::string RNA_function_as_string_keywords( bContext *C, FunctionRNA *func, bool as_function, bool all_args, int max_prop_length); /* Function */ diff --git a/source/blender/makesrna/RNA_path.hh b/source/blender/makesrna/RNA_path.hh index 0d7dbbced0c..b909e0a9c8f 100644 --- a/source/blender/makesrna/RNA_path.hh +++ b/source/blender/makesrna/RNA_path.hh @@ -15,6 +15,9 @@ * UI code or Actions, though efficiency is a concern. */ +#include +#include + #include "RNA_types.hh" struct ListBase; @@ -177,7 +180,8 @@ bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_el * \param needle: Custom property object to find. * \return Relative path or NULL. */ -char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *needle); +std::optional RNA_path_from_struct_to_idproperty(PointerRNA *ptr, + const IDProperty *needle); /** * Find the actual ID pointer and path from it to the given ID. @@ -188,67 +192,73 @@ char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *need */ ID *RNA_find_real_ID_and_path(ID *id, const char **r_path); -char *RNA_path_from_ID_to_struct(const PointerRNA *ptr); +std::optional RNA_path_from_ID_to_struct(const PointerRNA *ptr); -char *RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, ID **r_real); +std::optional RNA_path_from_real_ID_to_struct(Main *bmain, + const PointerRNA *ptr, + ID **r_real); -char *RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop); +std::optional RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop); -char *RNA_path_from_ptr_to_property_index(const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index); +std::string RNA_path_from_ptr_to_property_index(const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index); /** * \param index_dim: The dimension to show, 0 disables. 1 for 1d array, 2 for 2d. etc. * \param index: The *flattened* index to use when \a `index_dim > 0`, * this is expanded when used with multi-dimensional arrays. */ -char *RNA_path_from_ID_to_property_index(const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index); +std::optional RNA_path_from_ID_to_property_index(const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index); -char *RNA_path_from_real_ID_to_property_index(Main *bmain, - const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index, - ID **r_real_id); +std::optional RNA_path_from_real_ID_to_property_index(Main *bmain, + const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index, + ID **r_real_id); /** * \return the path to given ptr/prop from the closest ancestor of given type, * if any (else return NULL). */ -char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, - PropertyRNA *prop, - const StructRNA *type); +std::optional RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, + PropertyRNA *prop, + const StructRNA *type); /** * Get the ID as a python representation, eg: * bpy.data.foo["bar"] */ -char *RNA_path_full_ID_py(ID *id); +std::string RNA_path_full_ID_py(ID *id); /** * Get the ID.struct as a python representation, eg: * bpy.data.foo["bar"].some_struct */ -char *RNA_path_full_struct_py(const PointerRNA *ptr); +std::optional RNA_path_full_struct_py(const PointerRNA *ptr); /** * Get the ID.struct.property as a python representation, eg: * bpy.data.foo["bar"].some_struct.some_prop[10] */ -char *RNA_path_full_property_py_ex(const PointerRNA *ptr, - PropertyRNA *prop, - int index, - bool use_fallback); -char *RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index); +std::optional RNA_path_full_property_py_ex(const PointerRNA *ptr, + PropertyRNA *prop, + int index, + bool use_fallback); +std::optional RNA_path_full_property_py(const PointerRNA *ptr, + PropertyRNA *prop, + int index); /** * Get the struct.property as a python representation, eg: * some_struct.some_prop[10] */ -char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index); +std::optional RNA_path_struct_property_py(PointerRNA *ptr, + PropertyRNA *prop, + int index); /** * Get the struct.property as a python representation, eg: * some_prop[10] */ -char *RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index); +std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index); diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 4e70618c5cd..425d5e6674f 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -257,6 +257,7 @@ set(INC ../../render ../../../../intern/clog ../../../../intern/cycles/blender + ../../../../extern/fmtlib/include ../../../../intern/memutil ../../../../intern/mantaflow/extern @@ -487,6 +488,7 @@ set(SRC set(LIB PRIVATE bf::animrig PRIVATE bf::dna + PRIVATE extern_fmtlib bf_editor_space_api bf_editor_animation diff --git a/source/blender/makesrna/intern/rna_access.cc b/source/blender/makesrna/intern/rna_access.cc index de090bc452c..6f35a88d7a2 100644 --- a/source/blender/makesrna/intern/rna_access.cc +++ b/source/blender/makesrna/intern/rna_access.cc @@ -10,6 +10,9 @@ #include #include #include +#include + +#include #include "MEM_guardedalloc.h" @@ -2217,7 +2220,7 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop) } bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) { - char *path = RNA_path_from_ID_to_property(ptr, prop); + const std::optional path = RNA_path_from_ID_to_property(ptr, prop); bool ret = false; if (path) { @@ -2225,10 +2228,9 @@ bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) PropertyRNA *r_prop; PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id); - if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) { + if (RNA_path_resolve(&id_ptr, path->c_str(), &r_ptr, &r_prop) == true) { ret = (prop == r_prop); } - MEM_freeN(path); } return ret; @@ -5713,15 +5715,14 @@ bool RNA_property_is_unlink(PropertyRNA *prop) return (flag & (PROP_NEVER_UNLINK | PROP_NEVER_NULL)) == 0; } -char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) +std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) { - DynStr *dynstr = BLI_dynstr_new(); - char *cstring; + std::stringstream ss; const char *propname; int first_time = 1; - BLI_dynstr_append(dynstr, "{"); + ss << '{'; RNA_STRUCT_BEGIN (ptr, prop) { propname = RNA_property_identifier(prop); @@ -5731,27 +5732,24 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr) } if (first_time == 0) { - BLI_dynstr_append(dynstr, ", "); + ss << ", "; } first_time = 0; - cstring = RNA_property_as_string(C, ptr, prop, -1, INT_MAX); - BLI_dynstr_appendf(dynstr, "\"%s\":%s", propname, cstring); - MEM_freeN(cstring); + const std::string str = RNA_property_as_string(C, ptr, prop, -1, INT_MAX); + ss << fmt::format("\"{}\":{}", propname, str); } RNA_STRUCT_END; - BLI_dynstr_append(dynstr, "}"); + ss << '}'; - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; + return ss.str(); } -static char *rna_pointer_as_string__bldata(PointerRNA *ptr) +static std::optional rna_pointer_as_string__bldata(PointerRNA *ptr) { if (ptr->type == nullptr || ptr->owner_id == nullptr) { - return BLI_strdup("None"); + return "None"; } if (RNA_struct_is_ID(ptr->type)) { return RNA_path_full_ID_py(ptr->owner_id); @@ -5759,14 +5757,14 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr) return RNA_path_full_struct_py(ptr); } -char *RNA_pointer_as_string(bContext *C, - PointerRNA *ptr, - PropertyRNA *prop_ptr, - PointerRNA *ptr_prop) +std::optional RNA_pointer_as_string(bContext *C, + PointerRNA *ptr, + PropertyRNA *prop_ptr, + PointerRNA *ptr_prop) { IDProperty *prop; if (ptr_prop->data == nullptr) { - return BLI_strdup("None"); + return "None"; } if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) { return RNA_pointer_as_string_id(C, ptr_prop); @@ -5774,20 +5772,20 @@ char *RNA_pointer_as_string(bContext *C, return rna_pointer_as_string__bldata(ptr_prop); } -char *RNA_pointer_as_string_keywords_ex(bContext *C, - PointerRNA *ptr, - const bool as_function, - const bool all_args, - const bool nested_args, - const int max_prop_length, - PropertyRNA *iterprop) +std::string RNA_pointer_as_string_keywords_ex(bContext *C, + PointerRNA *ptr, + const bool as_function, + const bool all_args, + const bool nested_args, + const int max_prop_length, + PropertyRNA *iterprop) { const char *arg_name = nullptr; PropertyRNA *prop; - DynStr *dynstr = BLI_dynstr_new(); - char *cstring, *buf; + std::stringstream ss; + bool first_iter = true; int flag, flag_parameter; @@ -5813,7 +5811,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, if (as_function && (prop->flag_parameter & PARM_REQUIRED)) { /* required args don't have useful defaults */ - BLI_dynstr_appendf(dynstr, first_iter ? "%s" : ", %s", arg_name); + ss << fmt::format(first_iter ? "{}" : ", {}", arg_name); first_iter = false; } else { @@ -5827,39 +5825,37 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, } if (ok) { + std::string buf; if (as_function && RNA_property_type(prop) == PROP_POINTER) { /* don't expand pointers for functions */ if (flag & PROP_NEVER_NULL) { /* we can't really do the right thing here. arg=arg?, hrmf! */ - buf = BLI_strdup(arg_name); + buf = arg_name; } else { - buf = BLI_strdup("None"); + buf = "None"; } } else { buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length); } - BLI_dynstr_appendf(dynstr, first_iter ? "%s=%s" : ", %s=%s", arg_name, buf); + ss << fmt::format(first_iter ? "{}={}" : ", {}={}", arg_name, buf); first_iter = false; - MEM_freeN(buf); } } } RNA_PROP_END; - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; + return ss.str(); } -char *RNA_pointer_as_string_keywords(bContext *C, - PointerRNA *ptr, - const bool as_function, - const bool all_args, - const bool nested_args, - const int max_prop_length) +std::string RNA_pointer_as_string_keywords(bContext *C, + PointerRNA *ptr, + const bool as_function, + const bool all_args, + const bool nested_args, + const int max_prop_length) { PropertyRNA *iterprop; @@ -5869,17 +5865,15 @@ char *RNA_pointer_as_string_keywords(bContext *C, C, ptr, as_function, all_args, nested_args, max_prop_length, iterprop); } -char *RNA_function_as_string_keywords(bContext *C, - FunctionRNA *func, - const bool as_function, - const bool all_args, - const int max_prop_length) +std::string RNA_function_as_string_keywords(bContext *C, + FunctionRNA *func, + const bool as_function, + const bool all_args, + const int max_prop_length) { - PropertyRNA *iterprop; - PointerRNA funcptr = RNA_pointer_create(nullptr, &RNA_Function, func); - iterprop = RNA_struct_find_property(&funcptr, "parameters"); + PropertyRNA *iterprop = RNA_struct_find_property(&funcptr, "parameters"); RNA_struct_iterator_property(funcptr.type); @@ -5920,7 +5914,7 @@ static void *rna_array_as_string_alloc( } } -static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dynstr) +static void rna_array_as_string_elem(int type, void **buf_p, int len, std::stringstream &ss) { /* This will print a comma separated string of the array elements from * buf start to len. We will add a comma if len == 1 to preserve tuples. */ @@ -5929,7 +5923,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy case PROP_BOOLEAN: { bool *buf = static_cast(*buf_p); for (int i = 0; i < len; i++, buf++) { - BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%s, " : "%s", bool_as_py_string(*buf)); + ss << fmt::format((i < end || !end) ? "{}, " : "{}", bool_as_py_string(*buf)); } *buf_p = buf; break; @@ -5937,7 +5931,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy case PROP_INT: { int *buf = static_cast(*buf_p); for (int i = 0; i < len; i++, buf++) { - BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%d, " : "%d", *buf); + ss << fmt::format((i < end || !end) ? "{}, " : "{}", *buf); } *buf_p = buf; break; @@ -5945,7 +5939,7 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy case PROP_FLOAT: { float *buf = static_cast(*buf_p); for (int i = 0; i < len; i++, buf++) { - BLI_dynstr_appendf(dynstr, (i < end || !end) ? "%g, " : "%g", *buf); + ss << fmt::format((i < end || !end) ? "%g, " : "%g", *buf); } *buf_p = buf; break; @@ -5956,27 +5950,27 @@ static void rna_array_as_string_elem(int type, void **buf_p, int len, DynStr *dy } static void rna_array_as_string_recursive( - int type, void **buf_p, int totdim, const int *dim_size, DynStr *dynstr) + int type, void **buf_p, int totdim, const int *dim_size, std::stringstream &ss) { - BLI_dynstr_append(dynstr, "("); + ss << '('; if (totdim > 1) { totdim--; const int end = dim_size[totdim] - 1; for (int i = 0; i <= end; i++) { - rna_array_as_string_recursive(type, buf_p, totdim, dim_size, dynstr); + rna_array_as_string_recursive(type, buf_p, totdim, dim_size, ss); if (i < end || !end) { - BLI_dynstr_append(dynstr, ", "); + ss << ", "; } } } else { - rna_array_as_string_elem(type, buf_p, dim_size[0], dynstr); + rna_array_as_string_elem(type, buf_p, dim_size[0], ss); } - BLI_dynstr_append(dynstr, ")"); + ss << ')'; } static void rna_array_as_string( - int type, int len, PointerRNA *ptr, PropertyRNA *prop, DynStr *dynstr) + int type, int len, PointerRNA *ptr, PropertyRNA *prop, std::stringstream &ss) { void *buf_end; void *buf = rna_array_as_string_alloc(type, len, ptr, prop, &buf_end); @@ -5985,59 +5979,57 @@ static void rna_array_as_string( totdim = RNA_property_array_dimension(ptr, prop, dim_size); - rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, dynstr); + rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, ss); BLI_assert(buf_step == buf_end); MEM_freeN(buf); } -char *RNA_property_as_string( +std::string RNA_property_as_string( bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length) { int type = RNA_property_type(prop); int len = RNA_property_array_length(ptr, prop); - DynStr *dynstr = BLI_dynstr_new(); - char *cstring; + std::stringstream ss; /* see if we can coerce into a python type - PropertyType */ switch (type) { case PROP_BOOLEAN: if (len == 0) { - BLI_dynstr_append(dynstr, bool_as_py_string(RNA_property_boolean_get(ptr, prop))); + ss << bool_as_py_string(RNA_property_boolean_get(ptr, prop)); } else { if (index != -1) { - BLI_dynstr_append(dynstr, - bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index))); + ss << bool_as_py_string(RNA_property_boolean_get_index(ptr, prop, index)); } else { - rna_array_as_string(type, len, ptr, prop, dynstr); + rna_array_as_string(type, len, ptr, prop, ss); } } break; case PROP_INT: if (len == 0) { - BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop)); + ss << RNA_property_int_get(ptr, prop); } else { if (index != -1) { - BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get_index(ptr, prop, index)); + ss << RNA_property_int_get_index(ptr, prop, index); } else { - rna_array_as_string(type, len, ptr, prop, dynstr); + rna_array_as_string(type, len, ptr, prop, ss); } } break; case PROP_FLOAT: if (len == 0) { - BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop)); + ss << fmt::format("{:g}", RNA_property_float_get(ptr, prop)); } else { if (index != -1) { - BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get_index(ptr, prop, index)); + ss << fmt::format("{:g}", RNA_property_float_get_index(ptr, prop, index)); } else { - rna_array_as_string(type, len, ptr, prop, dynstr); + rna_array_as_string(type, len, ptr, prop, ss); } } break; @@ -6054,7 +6046,7 @@ char *RNA_property_as_string( RNA_property_string_get(ptr, prop, buf); BLI_str_escape(buf_esc, buf, length * 2 + 1); MEM_freeN(buf); - BLI_dynstr_appendf(dynstr, "\"%s\"", buf_esc); + ss << fmt::format("\"{}\"", buf_esc); MEM_freeN(buf_esc); break; } @@ -6069,7 +6061,7 @@ char *RNA_property_as_string( const EnumPropertyItem *item_array; bool free; - BLI_dynstr_append(dynstr, "{"); + ss << "{"; RNA_property_enum_items(C, ptr, prop, &item_array, nullptr, &free); if (item_array) { @@ -6077,7 +6069,7 @@ char *RNA_property_as_string( bool is_first = true; for (; item->identifier; item++) { if (item->identifier[0] && item->value & val) { - BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier); + ss << fmt::format(is_first ? "'%s'" : ", '%s'", item->identifier); is_first = false; } } @@ -6087,32 +6079,30 @@ char *RNA_property_as_string( } } - BLI_dynstr_append(dynstr, "}"); + ss << "}"; } else { /* annoying exception, don't confuse with dictionary syntax above: {} */ - BLI_dynstr_append(dynstr, "set()"); + ss << "set()"; } } else if (RNA_property_enum_identifier(C, ptr, prop, val, &identifier)) { - BLI_dynstr_appendf(dynstr, "'%s'", identifier); + ss << fmt::format("'{}'", identifier); } else { - BLI_dynstr_append(dynstr, "''"); + return "''"; } break; } case PROP_POINTER: { PointerRNA tptr = RNA_property_pointer_get(ptr, prop); - cstring = RNA_pointer_as_string(C, ptr, prop, &tptr); - BLI_dynstr_append(dynstr, cstring); - MEM_freeN(cstring); + ss << RNA_pointer_as_string(C, ptr, prop, &tptr).value_or(""); break; } case PROP_COLLECTION: { int i = 0; CollectionPropertyIterator collect_iter; - BLI_dynstr_append(dynstr, "["); + ss << "["; for (RNA_property_collection_begin(ptr, prop, &collect_iter); (i < max_prop_length) && collect_iter.valid; @@ -6121,27 +6111,22 @@ char *RNA_property_as_string( PointerRNA itemptr = collect_iter.ptr; if (i != 0) { - BLI_dynstr_append(dynstr, ", "); + ss << ", "; } /* now get every prop of the collection */ - cstring = RNA_pointer_as_string(C, ptr, prop, &itemptr); - BLI_dynstr_append(dynstr, cstring); - MEM_freeN(cstring); + ss << RNA_pointer_as_string(C, ptr, prop, &itemptr).value_or(""); } RNA_property_collection_end(&collect_iter); - BLI_dynstr_append(dynstr, "]"); + ss << "]"; break; } default: - BLI_dynstr_append(dynstr, "''"); /* TODO */ - break; + return "''"; /* TODO */ } - cstring = BLI_dynstr_get_cstring(dynstr); - BLI_dynstr_free(dynstr); - return cstring; + return ss.str(); } /* Function */ diff --git a/source/blender/makesrna/intern/rna_access_compare_override.cc b/source/blender/makesrna/intern/rna_access_compare_override.cc index d72e1ab1790..cca75d6039c 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.cc +++ b/source/blender/makesrna/intern/rna_access_compare_override.cc @@ -101,12 +101,10 @@ static ID *rna_property_override_property_real_id_owner(Main * /*bmain*/, return owner_id; } - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); - if (rna_path) { - *r_rna_path = rna_path; + if (const std::optional rna_path = RNA_path_from_ID_to_property(ptr, prop)) { + *r_rna_path = BLI_strdup(rna_path->c_str()); if (rna_path_prefix != nullptr) { - *r_rna_path = BLI_sprintfN("%s%s", rna_path_prefix, rna_path); - MEM_freeN(rna_path); + *r_rna_path = BLI_sprintfN("%s%s", rna_path_prefix, rna_path->c_str()); } return owner_id; @@ -191,14 +189,15 @@ bool RNA_property_overridable_library_set(PointerRNA * /*ptr*/, bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop) { - char *rna_path = RNA_path_from_ID_to_property(ptr, prop); + const std::optional rna_path = RNA_path_from_ID_to_property(ptr, prop); ID *id = ptr->owner_id; - if (rna_path == nullptr || id == nullptr || !ID_IS_OVERRIDE_LIBRARY(id)) { + if (!rna_path || id == nullptr || !ID_IS_OVERRIDE_LIBRARY(id)) { return false; } - return (BKE_lib_override_library_property_find(id->override_library, rna_path) != nullptr); + return (BKE_lib_override_library_property_find(id->override_library, rna_path->c_str()) != + nullptr); } bool RNA_property_comparable(PointerRNA * /*ptr*/, PropertyRNA *prop) @@ -725,8 +724,7 @@ bool RNA_struct_override_matches(Main *bmain, #define RNA_PATH_BUFFSIZE 8192 - char rna_path_buffer[RNA_PATH_BUFFSIZE]; - char *rna_path = rna_path_buffer; + std::optional rna_path; size_t rna_path_len = 0; /* XXX TODO: this will have to be refined to handle collections insertions, and array items. */ @@ -736,6 +734,9 @@ bool RNA_struct_override_matches(Main *bmain, const char *prop_name = prop_local.identifier; const size_t prop_name_len = strlen(prop_name); + char rna_path_buffer[RNA_PATH_BUFFSIZE]; + char *rna_path_c = rna_path_buffer; + /* Inlined building (significantly more efficient). */ if (!prop_local.is_idprop) { rna_path_len = root_path_len + 1 + prop_name_len; @@ -743,46 +744,46 @@ bool RNA_struct_override_matches(Main *bmain, rna_path = static_cast(MEM_mallocN(rna_path_len + 1, __func__)); } - memcpy(rna_path, root_path, root_path_len); - rna_path[root_path_len] = '.'; - memcpy(rna_path + root_path_len + 1, prop_name, prop_name_len); - rna_path[rna_path_len] = '\0'; + memcpy(rna_path_c, root_path, root_path_len); + rna_path_c[root_path_len] = '.'; + memcpy(rna_path_c + root_path_len + 1, prop_name, prop_name_len); + rna_path_c[rna_path_len] = '\0'; } else { rna_path_len = root_path_len + 2 + prop_name_len + 2; if (rna_path_len >= RNA_PATH_BUFFSIZE) { - rna_path = static_cast(MEM_mallocN(rna_path_len + 1, __func__)); + rna_path_c = static_cast(MEM_mallocN(rna_path_len + 1, __func__)); } - memcpy(rna_path, root_path, root_path_len); - rna_path[root_path_len] = '['; - rna_path[root_path_len + 1] = '"'; - memcpy(rna_path + root_path_len + 2, prop_name, prop_name_len); - rna_path[root_path_len + 2 + prop_name_len] = '"'; - rna_path[root_path_len + 2 + prop_name_len + 1] = ']'; - rna_path[rna_path_len] = '\0'; + memcpy(rna_path_c, root_path, root_path_len); + rna_path_c[root_path_len] = '['; + rna_path_c[root_path_len + 1] = '"'; + memcpy(rna_path_c + root_path_len + 2, prop_name, prop_name_len); + rna_path_c[root_path_len + 2 + prop_name_len] = '"'; + rna_path_c[root_path_len + 2 + prop_name_len + 1] = ']'; + rna_path_c[rna_path_len] = '\0'; } + + rna_path.emplace(rna_path_c); } else { /* This is rather slow, but is not much called, so not really worth optimizing. */ rna_path = RNA_path_from_ID_to_property(ptr_local, rawprop); - if (rna_path != nullptr) { - rna_path_len = strlen(rna_path); + if (rna_path) { + rna_path_len = rna_path->size(); } } - if (rna_path == nullptr) { + if (!rna_path) { continue; } - CLOG_INFO(&LOG, 5, "Override Checking %s", rna_path); + CLOG_INFO(&LOG, 5, "Override Checking %s", rna_path->c_str()); - IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(liboverride, rna_path); + IDOverrideLibraryProperty *op = BKE_lib_override_library_property_find(liboverride, + rna_path->c_str()); if (ignore_overridden && op != nullptr) { BKE_lib_override_library_operations_tag(op, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false); - if (rna_path != rna_path_buffer) { - MEM_freeN(rna_path); - } continue; } @@ -796,7 +797,7 @@ bool RNA_struct_override_matches(Main *bmain, const int diff = rna_property_override_diff(bmain, &prop_local, &prop_reference, - rna_path, + rna_path->c_str(), rna_path_len, RNA_EQ_STRICT, liboverride, @@ -818,7 +819,7 @@ bool RNA_struct_override_matches(Main *bmain, if (diff != 0) { /* XXX TODO: refine this for per-item overriding of arrays... */ - op = BKE_lib_override_library_property_find(liboverride, rna_path); + op = BKE_lib_override_library_property_find(liboverride, rna_path->c_str()); IDOverrideLibraryPropertyOperation *opop = static_cast( op ? op->operations.first : nullptr); @@ -868,14 +869,15 @@ bool RNA_struct_override_matches(Main *bmain, CLOG_INFO(&LOG, 2, "Failed to restore forbidden liboverride `%s` for override data '%s'", - rna_path, + rna_path->c_str(), ptr_local->owner_id->name); } } else { if (op == nullptr) { /* An override property is needed, create a temp one if necessary. */ - op = BKE_lib_override_library_property_get(liboverride, rna_path, nullptr); + op = BKE_lib_override_library_property_get( + liboverride, rna_path->c_str(), nullptr); BKE_lib_override_library_operations_tag(op, LIBOVERRIDE_PROP_OP_TAG_UNUSED, true); } IDOverrideLibraryPropertyOperation *opop_restore = @@ -918,18 +920,11 @@ bool RNA_struct_override_matches(Main *bmain, /* This property is not overridden, and differs from reference, so we have no match. */ matching = false; if (!(do_create || do_restore || do_tag_for_restore)) { - /* Since we have no 'changing' action allowed, we can break here. */ - if (rna_path != rna_path_buffer) { - MEM_freeN(rna_path); - } + break; } } } - - if (rna_path != rna_path_buffer) { - MEM_freeN(rna_path); - } #undef RNA_PATH_BUFFSIZE } RNA_property_collection_end(&iter); diff --git a/source/blender/makesrna/intern/rna_color.cc b/source/blender/makesrna/intern/rna_color.cc index eaf29264be8..7d20a3c7e7d 100644 --- a/source/blender/makesrna/intern/rna_color.cc +++ b/source/blender/makesrna/intern/rna_color.cc @@ -181,7 +181,6 @@ static char *rna_ColorRamp_path(const PointerRNA *ptr) case ID_NT: { bNodeTree *ntree = (bNodeTree *)id; bNode *node; - char *node_path; for (node = static_cast(ntree->nodes.first); node; node = node->next) { if (ELEM(node->type, SH_NODE_VALTORGB, CMP_NODE_VALTORGB, TEX_NODE_VALTORGB)) { @@ -190,9 +189,8 @@ static char *rna_ColorRamp_path(const PointerRNA *ptr) * prepend path from ID to the node */ PointerRNA node_ptr = RNA_pointer_create(id, &RNA_Node, node); - node_path = RNA_path_from_ID_to_struct(&node_ptr); - path = BLI_sprintfN("%s.color_ramp", node_path); - MEM_freeN(node_path); + std::string node_path = RNA_path_from_ID_to_struct(&node_ptr).value_or(""); + path = BLI_sprintfN("%s.color_ramp", node_path.c_str()); } } } diff --git a/source/blender/makesrna/intern/rna_path.cc b/source/blender/makesrna/intern/rna_path.cc index 4312210d19b..8b146d6904b 100644 --- a/source/blender/makesrna/intern/rna_path.cc +++ b/source/blender/makesrna/intern/rna_path.cc @@ -9,10 +9,13 @@ #include #include +#include + #include "BLI_alloca.h" #include "BLI_dynstr.h" #include "BLI_listbase.h" #include "BLI_string.h" +#include "BLI_string_ref.hh" #include "BLI_utildefines.h" #include "BKE_idprop.h" @@ -894,17 +897,18 @@ static char *rna_idp_path(PointerRNA *ptr, return path; } -char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, const IDProperty *needle) +std::optional RNA_path_from_struct_to_idproperty(PointerRNA *ptr, + const IDProperty *needle) { const IDProperty *haystack = RNA_struct_idprops(ptr, false); if (haystack) { /* can fail when called on bones */ return rna_idp_path(ptr, haystack, needle, nullptr); } - return nullptr; + return std::nullopt; } -static char *rna_path_from_ID_to_idpgroup(const PointerRNA *ptr) +static std::optional rna_path_from_ID_to_idpgroup(const PointerRNA *ptr) { BLI_assert(ptr->owner_id != nullptr); @@ -947,7 +951,10 @@ ID *RNA_find_real_ID_and_path(ID *id, const char **r_path) return (owner_id != nullptr) ? owner_id : id; } -static char *rna_prepend_real_ID_path(Main * /*bmain*/, ID *id, char *path, ID **r_real_id) +static std::optional rna_prepend_real_ID_path(Main * /*bmain*/, + ID *id, + const blender::StringRef path, + ID **r_real_id) { if (r_real_id != nullptr) { *r_real_id = nullptr; @@ -960,36 +967,36 @@ static char *rna_prepend_real_ID_path(Main * /*bmain*/, ID *id, char *path, ID * *r_real_id = real_id; } - if (path != nullptr) { - char *new_path = nullptr; - + if (!path.is_empty()) { if (real_id) { if (prefix[0]) { - new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path); - } - else { - return path; + return fmt::format("{}{}{}", prefix, path[0] == '[' ? "" : ".", std::string_view(path)); } + return path; } - - MEM_freeN(path); - return new_path; } - return prefix[0] != '\0' ? BLI_strdup(prefix) : nullptr; + + if (prefix[0] == '\0') { + return std::nullopt; + } + + return prefix; } -char *RNA_path_from_ID_to_struct(const PointerRNA *ptr) +std::optional RNA_path_from_ID_to_struct(const PointerRNA *ptr) { - char *ptrpath = nullptr; + std::optional ptrpath; if (!ptr->owner_id || !ptr->data) { - return nullptr; + return std::nullopt; } if (!RNA_struct_is_ID(ptr->type)) { if (ptr->type->path) { /* if type has a path to some ID, use it */ - ptrpath = ptr->type->path((PointerRNA *)ptr); + char *path_cstr = ptr->type->path((PointerRNA *)ptr); + ptrpath = path_cstr; + MEM_freeN(path_cstr); } else if (ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) { PropertyRNA *userprop; @@ -1001,10 +1008,11 @@ char *RNA_path_from_ID_to_struct(const PointerRNA *ptr) userprop = rna_struct_find_nested(&parentptr, ptr->type); if (userprop) { - ptrpath = BLI_strdup(RNA_property_identifier(userprop)); + ptrpath = RNA_property_identifier(userprop); } else { - return nullptr; /* can't do anything about this case yet... */ + /* can't do anything about this case yet... */ + return std::nullopt; } } else if (RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) { @@ -1012,19 +1020,21 @@ char *RNA_path_from_ID_to_struct(const PointerRNA *ptr) return rna_path_from_ID_to_idpgroup(ptr); } else { - return nullptr; + return std::nullopt; } } return ptrpath; } -char *RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, ID **r_real) +std::optional RNA_path_from_real_ID_to_struct(Main *bmain, + const PointerRNA *ptr, + ID **r_real) { - char *path = RNA_path_from_ID_to_struct(ptr); + const std::optional path = RNA_path_from_ID_to_struct(ptr); /* Null path is valid in that case, when given struct is an ID one. */ - return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real); + return rna_prepend_real_ID_path(bmain, ptr->owner_id, path.value_or(""), r_real); } static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH], @@ -1067,14 +1077,15 @@ static void rna_path_array_multi_string_from_flat_index(const PointerRNA *ptr, } } -static char *rna_path_from_ptr_to_property_index_ex( - const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, const char *path_prefix) +static std::string rna_path_from_ptr_to_property_index_ex(const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index, + const blender::StringRef path_prefix) { const bool is_rna = (prop->magic == RNA_MAGIC); - const char *propname; - char *path; - propname = RNA_property_identifier(prop); + const char *propname = RNA_property_identifier(prop); /* support indexing w/ multi-dimensional arrays */ char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1]; @@ -1086,107 +1097,98 @@ static char *rna_path_from_ptr_to_property_index_ex( ptr, prop, index_dim, index, index_str, sizeof(index_str)); } - if (path_prefix) { + if (!path_prefix.is_empty()) { if (is_rna) { - path = BLI_sprintfN("%s.%s%s", path_prefix, propname, index_str); - } - else { - char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); - path = BLI_sprintfN("%s[\"%s\"]%s", path_prefix, propname_esc, index_str); - } - } - else { - if (is_rna) { - if (index_dim == 0) { - /* Use direct duplication instead of #BLI_sprintfN because it's faster. */ - path = BLI_strdup(propname); - } - else { - path = BLI_sprintfN("%s%s", propname, index_str); - } - } - else { - char propname_esc[MAX_IDPROP_NAME * 2]; - BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); - path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str); + return fmt::format("{}.{}{}", std::string_view(path_prefix), propname, index_str); } + char propname_esc[MAX_IDPROP_NAME * 2]; + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); + return fmt::format("{}[\"{}\"]{}", std::string_view(path_prefix), propname_esc, index_str); } - return path; + if (is_rna) { + if (index_dim == 0) { + /* Use direct duplication instead of #fmt::format because it's faster. */ + return propname; + } + return fmt::format("{}{}", propname, index_str); + } + + char propname_esc[MAX_IDPROP_NAME * 2]; + BLI_str_escape(propname_esc, propname, sizeof(propname_esc)); + return fmt::format("[\"{}\"]{}", propname_esc, index_str); } -char *RNA_path_from_ptr_to_property_index(const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index) +std::string RNA_path_from_ptr_to_property_index(const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index) { - return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, nullptr); + return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, ""); } -char *RNA_path_from_ID_to_property_index(const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index) +std::optional RNA_path_from_ID_to_property_index(const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index) { if (!ptr->owner_id || !ptr->data) { - return nullptr; + return std::nullopt; } /* Path from ID to the struct holding this property. */ - char *ptrpath = RNA_path_from_ID_to_struct(ptr); + std::optional ptrpath = RNA_path_from_ID_to_struct(ptr); /* When there is no path and this is not an ID, there is no path to the ID. */ - char *path = ((ptrpath == nullptr) && !RNA_struct_is_ID(ptr->type)) ? - nullptr : - rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, ptrpath); - if (ptrpath != nullptr) { - MEM_freeN(ptrpath); + if (!ptrpath && !RNA_struct_is_ID(ptr->type)) { + return std::nullopt; } - return path; + return rna_path_from_ptr_to_property_index_ex(ptr, prop, index_dim, index, ptrpath.value_or("")); } -char *RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop) +std::optional RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop) { return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1); } -char *RNA_path_from_real_ID_to_property_index(Main *bmain, - const PointerRNA *ptr, - PropertyRNA *prop, - int index_dim, - int index, - ID **r_real_id) +std::optional RNA_path_from_real_ID_to_property_index(Main *bmain, + const PointerRNA *ptr, + PropertyRNA *prop, + int index_dim, + int index, + ID **r_real_id) { - char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index); + const std::optional path = RNA_path_from_ID_to_property_index( + ptr, prop, index_dim, index); + if (!path) { + return std::nullopt; + } /* Null path is always an error here, in that case do not return the 'fake ID from real ID' part * of the path either. */ - return path != nullptr ? rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id) : - nullptr; + return rna_prepend_real_ID_path(bmain, ptr->owner_id, path->c_str(), r_real_id); } -char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, - PropertyRNA *prop, - const StructRNA *type) +std::optional RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, + PropertyRNA *prop, + const StructRNA *type) { /* Try to recursively find an "type"'d ancestor, * to handle situations where path from ID is not enough. */ ListBase path_elems = {nullptr}; - char *path = nullptr; - char *full_path = RNA_path_from_ID_to_property(ptr, prop); - - if (full_path == nullptr) { - return nullptr; + const std::optional full_path = RNA_path_from_ID_to_property(ptr, prop); + if (!full_path) { + return std::nullopt; } PointerRNA idptr = RNA_id_pointer_create(ptr->owner_id); - if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) { + std::optional path; + if (RNA_path_resolve_elements(&idptr, full_path->c_str(), &path_elems)) { LISTBASE_FOREACH_BACKWARD (PropertyElemRNA *, prop_elem, &path_elems) { if (RNA_struct_is_a(prop_elem->ptr.type, type)) { - char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr); - if (ref_path) { - path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */ - MEM_freeN(ref_path); + if (const std::optional ref_path = RNA_path_from_ID_to_struct( + &prop_elem->ptr)) + { + path = blender::StringRef(*full_path).drop_prefix(ref_path->size() + 1); } break; } @@ -1195,11 +1197,10 @@ char *RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, BLI_freelistN(&path_elems); } - MEM_freeN(full_path); return path; } -char *RNA_path_full_ID_py(ID *id) +std::string RNA_path_full_ID_py(ID *id) { const char *path; ID *id_real = RNA_find_real_ID_and_path(id, &path); @@ -1226,65 +1227,47 @@ char *RNA_path_full_ID_py(ID *id) char id_esc[(sizeof(id->name) - 2) * 2]; BLI_str_escape(id_esc, id->name + 2, sizeof(id_esc)); - return BLI_sprintfN("bpy.data.%s[\"%s\"%s]%s%s", - BKE_idtype_idcode_to_name_plural(GS(id->name)), - id_esc, - lib_filepath_esc, - path[0] ? "." : "", - path); + return fmt::format("bpy.data.{}[\"{}\"{}]{}{}", + BKE_idtype_idcode_to_name_plural(GS(id->name)), + id_esc, + lib_filepath_esc, + path[0] ? "." : "", + path); } -char *RNA_path_full_struct_py(const PointerRNA *ptr) +std::optional RNA_path_full_struct_py(const PointerRNA *ptr) { - char *id_path; - char *data_path; - - char *ret; - if (!ptr->owner_id) { - return nullptr; + return std::nullopt; } /* never fails */ - id_path = RNA_path_full_ID_py(ptr->owner_id); + std::string id_path = RNA_path_full_ID_py(ptr->owner_id); - data_path = RNA_path_from_ID_to_struct(ptr); + std::optional data_path = RNA_path_from_ID_to_struct(ptr); /* XXX data_path may be null (see #36788), * do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */ - ret = BLI_sprintfN("%s.%s", id_path, data_path); - - if (data_path) { - MEM_freeN(data_path); - } - MEM_freeN(id_path); - - return ret; + return fmt::format("{}.{}", id_path, data_path.value_or("")); } -char *RNA_path_full_property_py_ex(const PointerRNA *ptr, - PropertyRNA *prop, - int index, - bool use_fallback) +std::optional RNA_path_full_property_py_ex(const PointerRNA *ptr, + PropertyRNA *prop, + int index, + bool use_fallback) { - char *id_path; const char *data_delim; - const char *data_path; - bool data_path_free; - - char *ret; if (!ptr->owner_id) { - return nullptr; + return std::nullopt; } /* never fails */ - id_path = RNA_path_full_ID_py(ptr->owner_id); + std::string id_path = RNA_path_full_ID_py(ptr->owner_id); - data_path = RNA_path_from_ID_to_property(ptr, prop); + std::optional data_path = RNA_path_from_ID_to_property(ptr, prop); if (data_path) { - data_delim = (data_path[0] == '[') ? "" : "."; - data_path_free = true; + data_delim = ((*data_path)[0] == '[') ? "" : "."; } else { if (use_fallback) { @@ -1295,66 +1278,49 @@ char *RNA_path_full_property_py_ex(const PointerRNA *ptr, else { data_delim = "."; } - data_path_free = false; } if ((index == -1) || (RNA_property_array_check(prop) == false)) { - ret = BLI_sprintfN("%s%s%s", id_path, data_delim, data_path); + return fmt::format("{}{}{}", id_path, data_delim, data_path.value_or("")); } - else { - ret = BLI_sprintfN("%s%s%s[%d]", id_path, data_delim, data_path, index); - } - MEM_freeN(id_path); - if (data_path_free) { - MEM_freeN((void *)data_path); - } - - return ret; + return fmt::format("{}{}{}[{}]", id_path, data_delim, data_path.value_or(""), index); } -char *RNA_path_full_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index) +std::optional RNA_path_full_property_py(const PointerRNA *ptr, + PropertyRNA *prop, + int index) { return RNA_path_full_property_py_ex(ptr, prop, index, false); } -char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index) +std::optional RNA_path_struct_property_py(PointerRNA *ptr, + PropertyRNA *prop, + int index) { - char *data_path; - - char *ret; - if (!ptr->owner_id) { - return nullptr; + return std::nullopt; } - data_path = RNA_path_from_ID_to_property(ptr, prop); + std::optional data_path = RNA_path_from_ID_to_property(ptr, prop); - if (data_path == nullptr) { + if (!data_path) { /* This may not be an ID at all, check for simple when pointer owns property. * TODO: more complex nested case. */ if (!RNA_struct_is_ID(ptr->type)) { const char *prop_identifier = RNA_property_identifier(prop); if (RNA_struct_find_property(ptr, prop_identifier) == prop) { - data_path = BLI_strdup(prop_identifier); + data_path = prop_identifier; } } } if ((index == -1) || (RNA_property_array_check(prop) == false)) { - ret = BLI_strdup(data_path); + return *data_path; } - else { - ret = BLI_sprintfN("%s[%d]", data_path, index); - } - - if (data_path) { - MEM_freeN(data_path); - } - - return ret; + return fmt::format("{}[{}]", data_path.value_or(""), index); } -char *RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index) +std::string RNA_path_property_py(const PointerRNA *ptr, PropertyRNA *prop, int index) { if (RNA_property_array_check(prop) == false) { index = -1; diff --git a/source/blender/python/intern/bpy_rna.cc b/source/blender/python/intern/bpy_rna.cc index fbd067a9700..133ebc8bdf6 100644 --- a/source/blender/python/intern/bpy_rna.cc +++ b/source/blender/python/intern/bpy_rna.cc @@ -924,10 +924,10 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) "bpy.data.%s[%R]", BKE_idtype_idcode_to_name_plural(GS(id->name)), tmp_str); } else { - const char *path; ID *real_id = nullptr; - path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id); - if (path != nullptr) { + const std::optional path = RNA_path_from_real_ID_to_struct( + G_MAIN, &self->ptr, &real_id); + if (path) { /* 'real_id' may be nullptr in some cases, although the only valid one is evaluated data, * which should have already been caught above. * So assert, but handle it without crashing for release builds. */ @@ -939,7 +939,7 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) ret = PyUnicode_FromFormat("bpy.data.%s[%R].%s", BKE_idtype_idcode_to_name_plural(GS(real_id->name)), tmp_str, - path); + path->c_str()); } else { /* Can't find the path, print something useful as a fallback. */ @@ -948,7 +948,6 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self) tmp_str, RNA_struct_identifier(self->ptr.type)); } - MEM_freeN((void *)path); } else { /* Can't find the path, print something useful as a fallback. */ @@ -1038,7 +1037,6 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, ID *id = self->ptr.owner_id; PyObject *tmp_str; PyObject *ret; - const char *path; PYRNA_PROP_CHECK_OBJ(self); @@ -1052,7 +1050,7 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, /* Note that using G_MAIN is absolutely not ideal, but we have no access to actual Main DB from * here. */ ID *real_id = nullptr; - path = RNA_path_from_real_ID_to_property_index( + const std::optional path = RNA_path_from_real_ID_to_property_index( G_MAIN, &self->ptr, self->prop, index_dim, index, &real_id); if (path) { @@ -1060,14 +1058,12 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, Py_DECREF(tmp_str); tmp_str = PyUnicode_FromString(real_id->name + 2); } - const char *data_delim = (path[0] == '[') ? "" : "."; + const char *data_delim = ((*path)[0] == '[') ? "" : "."; ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s", BKE_idtype_idcode_to_name_plural(GS(real_id->name)), tmp_str, data_delim, - path); - - MEM_freeN((void *)path); + path->c_str()); } else { /* Can't find the path, print something useful as a fallback. */ @@ -3892,7 +3888,6 @@ PyDoc_STRVAR( static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) { const char *name = nullptr; - const char *path; PropertyRNA *prop; PyObject *ret; @@ -3902,6 +3897,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) return nullptr; } + std::optional path; if (name) { prop = RNA_struct_find_property(&self->ptr, name); if (prop == nullptr) { @@ -3918,7 +3914,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) path = RNA_path_from_ID_to_struct(&self->ptr); } - if (path == nullptr) { + if (!path) { if (name) { PyErr_Format(PyExc_ValueError, "%.200s.path_from_id(\"%s\") found, but does not support path creation", @@ -3933,8 +3929,7 @@ static PyObject *pyrna_struct_path_from_id(BPy_StructRNA *self, PyObject *args) return nullptr; } - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); + ret = PyUnicode_FromString(path->c_str()); return ret; } @@ -3950,13 +3945,12 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) { - const char *path; PropertyRNA *prop = self->prop; PyObject *ret; - path = RNA_path_from_ID_to_property(&self->ptr, self->prop); + const std::optional path = RNA_path_from_ID_to_property(&self->ptr, self->prop); - if (path == nullptr) { + if (!path) { PyErr_Format(PyExc_ValueError, "%.200s.%.200s.path_from_id() does not support path creation for this type", RNA_struct_identifier(self->ptr.type), @@ -3964,8 +3958,7 @@ static PyObject *pyrna_prop_path_from_id(BPy_PropertyRNA *self) return nullptr; } - ret = PyUnicode_FromString(path); - MEM_freeN((void *)path); + ret = PyUnicode_FromString(path->c_str()); return ret; } @@ -4469,7 +4462,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) PointerRNA idptr; PointerRNA *base_ptr; - char *path_str; + std::optional path_str; if (newptr.owner_id) { idptr = RNA_id_pointer_create(newptr.owner_id); @@ -4485,10 +4478,8 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) ret = PyTuple_New(3); PyTuple_SET_ITEMS(ret, pyrna_struct_CreatePyObject(base_ptr), - PyUnicode_FromString(path_str), + PyUnicode_FromString(path_str->c_str()), PyLong_FromLong(newindex)); - - MEM_freeN(path_str); } else { ret = Py_None; @@ -6783,18 +6774,15 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject static PyObject *pyrna_func_doc_get(BPy_FunctionRNA *self, void * /*closure*/) { PyObject *ret; - char *args; - args = RNA_function_as_string_keywords(nullptr, self->func, true, true, INT_MAX); + std::string args = RNA_function_as_string_keywords(nullptr, self->func, true, true, INT_MAX); ret = PyUnicode_FromFormat("%.200s.%.200s(%.200s)\n%s", RNA_struct_identifier(self->ptr.type), RNA_function_identifier(self->func), - args, + args.c_str(), RNA_function_ui_description(self->func)); - MEM_freeN(args); - return ret; } diff --git a/source/blender/python/intern/bpy_rna_anim.cc b/source/blender/python/intern/bpy_rna_anim.cc index a7d501e2d98..9d3e0801b1f 100644 --- a/source/blender/python/intern/bpy_rna_anim.cc +++ b/source/blender/python/intern/bpy_rna_anim.cc @@ -142,7 +142,8 @@ static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr, *r_path_full = BLI_strdup(path); } else { - *r_path_full = RNA_path_from_ID_to_property(&r_ptr, prop); + const std::optional path_full = RNA_path_from_ID_to_property(&r_ptr, prop); + *r_path_full = path_full ? BLI_strdup(path_full->c_str()) : nullptr; if (*r_path_full == nullptr) { PyErr_Format(PyExc_TypeError, "%.200s could not make path to \"%s\"", error_prefix, path); @@ -176,8 +177,8 @@ static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr, return 0; } - char *path_prefix = RNA_path_from_ID_to_struct(ptr); - if (path_prefix == nullptr) { + const std::optional path_prefix = RNA_path_from_ID_to_struct(ptr); + if (!path_prefix) { PyErr_Format(PyExc_TypeError, "%.200s could not make path for type %s", error_prefix, @@ -186,12 +187,11 @@ static int pyrna_struct_anim_args_parse_no_resolve(PointerRNA *ptr, } if (*path == '[') { - *r_path_full = BLI_string_joinN(path_prefix, path); + *r_path_full = BLI_string_joinN(path_prefix->c_str(), path); } else { - *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix, path); + *r_path_full = BLI_string_join_by_sep_charN('.', path_prefix->c_str(), path); } - MEM_freeN(path_prefix); return 0; } diff --git a/source/blender/windowmanager/intern/wm_event_system.cc b/source/blender/windowmanager/intern/wm_event_system.cc index 70e18212050..41e4e5b62e9 100644 --- a/source/blender/windowmanager/intern/wm_event_system.cc +++ b/source/blender/windowmanager/intern/wm_event_system.cc @@ -2930,7 +2930,7 @@ static const char *keymap_handler_log_kmi_op_str(bContext *C, size_t buf_maxncpy) { /* The key-map item properties can further help distinguish this item from others. */ - char *kmi_props = nullptr; + std::optional kmi_props; if (kmi->properties != nullptr) { wmOperatorType *ot = WM_operatortype_find(kmi->idname, false); if (ot) { @@ -2940,10 +2940,7 @@ static const char *keymap_handler_log_kmi_op_str(bContext *C, kmi_props = IDP_reprN(kmi->properties, nullptr); } } - BLI_snprintf(buf, buf_maxncpy, "%s(%s)", kmi->idname, kmi_props ? kmi_props : ""); - if (kmi_props != nullptr) { - MEM_freeN(kmi_props); - } + BLI_snprintf(buf, buf_maxncpy, "%s(%s)", kmi->idname, kmi_props.value_or("").c_str()); return buf; } diff --git a/source/blender/windowmanager/intern/wm_operators.cc b/source/blender/windowmanager/intern/wm_operators.cc index fbafb80c990..6dce368b7bb 100644 --- a/source/blender/windowmanager/intern/wm_operators.cc +++ b/source/blender/windowmanager/intern/wm_operators.cc @@ -246,15 +246,14 @@ std::string WM_operator_pystring_ex(bContext *C, opmptr = &opmptr_default; } - char *cstring_args = RNA_pointer_as_string_id(C, opmptr); + std::string string_args = RNA_pointer_as_string_id(C, opmptr); if (first_op) { - ss << opm->type->idname << '=' << cstring_args; + ss << opm->type->idname << '=' << string_args; first_op = false; } else { - ss << ", " << opm->type->idname << '=' << cstring_args; + ss << ", " << opm->type->idname << '=' << string_args; } - MEM_freeN(cstring_args); if (opmptr == &opmptr_default) { WM_operator_properties_free(&opmptr_default); @@ -271,10 +270,8 @@ std::string WM_operator_pystring_ex(bContext *C, opptr = &opptr_default; } - char *cstring_args = RNA_pointer_as_string_keywords( + ss << RNA_pointer_as_string_keywords( C, opptr, false, all_args, macro_args_test, max_prop_length); - ss << cstring_args; - MEM_freeN(cstring_args); if (opptr == &opptr_default) { WM_operator_properties_free(&opptr_default); @@ -608,34 +605,31 @@ std::optional WM_context_path_resolve_property_full(const bContext } std::string member_id_data_path; if (is_id && !RNA_struct_is_ID(ptr->type)) { - char *data_path = RNA_path_from_ID_to_struct(ptr); - if (data_path != nullptr) { + std::optional data_path = RNA_path_from_ID_to_struct(ptr); + if (data_path) { if (prop != nullptr) { - char *prop_str = RNA_path_property_py(ptr, prop, index); + std::string prop_str = RNA_path_property_py(ptr, prop, index); if (prop_str[0] == '[') { - member_id_data_path = fmt::format("{}.{}", data_path, prop_str); + member_id_data_path = fmt::format("{}.{}", *data_path, prop_str); } else { - member_id_data_path = fmt::format("{}.{}.{}", member_id, data_path, prop_str); + member_id_data_path = fmt::format("{}.{}.{}", member_id, *data_path, prop_str); } - MEM_freeN(prop_str); } else { - member_id_data_path = fmt::format("{}.{}", member_id, data_path); + member_id_data_path = fmt::format("{}.{}", member_id, *data_path); } - MEM_freeN(data_path); } } else { if (prop != nullptr) { - char *prop_str = RNA_path_property_py(ptr, prop, index); + std::string prop_str = RNA_path_property_py(ptr, prop, index); if (prop_str[0] == '[') { member_id_data_path = fmt::format("{}{}", member_id, prop_str); } else { member_id_data_path = fmt::format("{}.{}", member_id, prop_str); } - MEM_freeN(prop_str); } else { member_id_data_path = member_id; @@ -673,22 +667,17 @@ std::optional WM_prop_pystring_assign(bContext *C, if (!lhs.has_value()) { /* Fallback to `bpy.data.foo[id]` if we don't find in the context. */ - if (char *lhs_cstr = RNA_path_full_property_py(ptr, prop, index)) { - lhs = lhs_cstr; - MEM_freeN(lhs_cstr); + if (std::optional lhs_str = RNA_path_full_property_py(ptr, prop, index)) { + lhs = lhs_str; } else { return std::nullopt; } } - char *rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX); - if (!rhs) { - return std::nullopt; - } + std::string rhs = RNA_property_as_string(C, ptr, prop, index, INT_MAX); std::string ret = fmt::format("{} = {}", lhs.value(), rhs); - MEM_freeN(rhs); return ret; } @@ -1523,12 +1512,12 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *region, void *user_ BLF_width(style->widget.uifont_id, data->title.c_str(), BLF_DRAW_STR_DUMMY_MAX)); /* Break Message into multiple lines. */ - std::vector message_lines; + blender::Vector message_lines; blender::StringRef messaged_trimmed = blender::StringRef(data->message).trim(); std::istringstream message_stream(messaged_trimmed); std::string line; while (std::getline(message_stream, line)) { - message_lines.push_back(line); + message_lines.append(line); text_width = std::max( text_width, int(BLF_width(style->widget.uifont_id, line.c_str(), BLF_DRAW_STR_DUMMY_MAX))); } diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.cc b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.cc index 7828a81ebae..460c94a7a82 100644 --- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.cc +++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.cc @@ -15,6 +15,7 @@ #include "BLI_ghash.h" #include "BLI_listbase.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "WM_message.hh" @@ -316,7 +317,9 @@ void WM_msg_subscribe_rna_params(wmMsgBus *mbus, if (msg_key->msg.params.data_path == nullptr) { if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.owner_id) { /* We assume prop type can't change. */ - msg_key->msg.params.data_path = RNA_path_from_ID_to_struct(&msg_key->msg.params.ptr); + const std::optional str = RNA_path_from_ID_to_struct( + &msg_key->msg.params.ptr); + msg_key->msg.params.data_path = str ? BLI_strdupn(str->c_str(), str->size()) : nullptr; } } }