diff options
-rw-r--r-- | source/blender/blenkernel/intern/action_bones.cc | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 24 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_string.h | 12 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string.c | 97 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_deps.c | 7 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 25 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_ipo_utils.c | 30 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_general.c | 9 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 16 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_select.c | 8 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_convert_armature.c | 8 | ||||
-rw-r--r-- | source/blender/io/collada/BCAnimationCurve.cpp | 5 | ||||
-rw-r--r-- | source/blender/io/collada/BCAnimationSampler.cpp | 5 |
13 files changed, 153 insertions, 99 deletions
diff --git a/source/blender/blenkernel/intern/action_bones.cc b/source/blender/blenkernel/intern/action_bones.cc index b8d185e6a81..1f2b7360b70 100644 --- a/source/blender/blenkernel/intern/action_bones.cc +++ b/source/blender/blenkernel/intern/action_bones.cc @@ -28,6 +28,7 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_armature_types.h" #include "MEM_guardedalloc.h" @@ -36,12 +37,11 @@ namespace blender::bke { void BKE_action_find_fcurves_with_bones(const bAction *action, FoundFCurveCallback callback) { LISTBASE_FOREACH (FCurve *, fcu, &action->curves) { - char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - if (!bone_name) { + char bone_name[MAXBONENAME]; + if (!BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) { continue; } callback(fcu, bone_name); - MEM_freeN(bone_name); } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index fb6cd5871f4..8e9c504dcbf 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -346,30 +346,30 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con return 0; } + const size_t quotedName_size = strlen(dataName) + 1; + char *quotedName = alloca(quotedName_size); + /* Search each F-Curve one by one. */ for (fcu = src->first; fcu; fcu = fcu->next) { /* Check if quoted string matches the path. */ if (fcu->rna_path == NULL) { continue; } - - char *quotedName = BLI_str_quoted_substrN(fcu->rna_path, dataPrefix); - if (quotedName == NULL) { + /* Skipping names longer than `quotedName_size` is OK since we're after an exact match. */ + if (!BLI_str_quoted_substr(fcu->rna_path, dataPrefix, quotedName, quotedName_size)) { + continue; + } + if (!STREQ(quotedName, dataName)) { continue; } /* Check if the quoted name matches the required name. */ - if (STREQ(quotedName, dataName)) { - LinkData *ld = MEM_callocN(sizeof(LinkData), __func__); - - ld->data = fcu; - BLI_addtail(dst, ld); + LinkData *ld = MEM_callocN(sizeof(LinkData), __func__); - matches++; - } + ld->data = fcu; + BLI_addtail(dst, ld); - /* Always free the quoted string, since it needs freeing. */ - MEM_freeN(quotedName); + matches++; } /* Return the number of matches. */ return matches; diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index c20376c42b9..eab39433796 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -65,7 +65,10 @@ bool BLI_str_quoted_substr_range(const char *__restrict str, char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; - +bool BLI_str_quoted_substr(const char *__restrict str, + const char *__restrict prefix, + char *result, + size_t result_maxlen); char *BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT @@ -97,8 +100,15 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL(); +size_t BLI_str_unescape_ex(char *__restrict dst, + const char *__restrict src, + const size_t src_maxncpy, + /* Additional arguments. */ + const size_t dst_maxncpy, + bool *r_is_complete) ATTR_NONNULL(); size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) ATTR_NONNULL(); + const char *BLI_str_escape_find_quote(const char *str) ATTR_NONNULL(); size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL(); diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 0be8700810e..fab5e44de25 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -360,6 +360,27 @@ size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const si return len; } +BLI_INLINE bool str_unescape_pair(char c_next, char *r_out) +{ +#define CASE_PAIR(value_src, value_dst) \ + case value_src: { \ + *r_out = value_dst; \ + return true; \ + } + switch (c_next) { + CASE_PAIR('"', '"'); /* Quote. */ + CASE_PAIR('\\', '\\'); /* Backslash. */ + CASE_PAIR('t', '\t'); /* Tab. */ + CASE_PAIR('n', '\n'); /* Newline. */ + CASE_PAIR('r', '\r'); /* Carriage return. */ + CASE_PAIR('a', '\a'); /* Bell. */ + CASE_PAIR('b', '\b'); /* Backspace. */ + CASE_PAIR('f', '\f'); /* Form-feed. */ + } +#undef CASE_PAIR + return false; +} + /** * This roughly matches C and Python's string escaping with double quotes - `"`. * @@ -368,31 +389,53 @@ size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const si * * \param dst: The destination string, at least the size of `strlen(src) + 1`. * \param src: The escaped source string. - * \param dst_maxncpy: The maximum number of bytes allowable to copy. + * \param src_maxncpy: The maximum number of bytes allowable to copy from `src`. + * \param dst_maxncpy: The maximum number of bytes allowable to copy into `dst`. + * \param r_is_complete: Set to true when + */ +size_t BLI_str_unescape_ex(char *__restrict dst, + const char *__restrict src, + const size_t src_maxncpy, + /* Additional arguments to #BLI_str_unescape */ + const size_t dst_maxncpy, + bool *r_is_complete) +{ + size_t len = 0; + bool is_complete = true; + for (const char *src_end = src + src_maxncpy; (src < src_end) && *src; src++) { + if (UNLIKELY(len == dst_maxncpy)) { + is_complete = false; + break; + } + char c = *src; + if (UNLIKELY(c == '\\') && (str_unescape_pair(*(src + 1), &c))) { + src++; + } + dst[len++] = c; + } + dst[len] = 0; + *r_is_complete = is_complete; + return len; +} + +/** + * See #BLI_str_unescape_ex doc-string. + * + * This function makes the assumption that `dst` always has + * at least `src_maxncpy` bytes available. + * + * Use #BLI_str_unescape_ex if `dst` has a smaller fixed size. * - * \note This is used for parsing animation paths in blend files. + * \note This is used for parsing animation paths in blend files (runs often). */ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) { size_t len = 0; - for (size_t i = 0; i < src_maxncpy && (*src != '\0'); i++, src++) { + for (const char *src_end = src + src_maxncpy; (src < src_end) && *src; src++) { char c = *src; - if (c == '\\') { - char c_next = *(src + 1); - if (((c_next == '"') && ((void)(c = '"'), true)) || /* Quote. */ - ((c_next == '\\') && ((void)(c = '\\'), true)) || /* Backslash. */ - ((c_next == 't') && ((void)(c = '\t'), true)) || /* Tab. */ - ((c_next == 'n') && ((void)(c = '\n'), true)) || /* Newline. */ - ((c_next == 'r') && ((void)(c = '\r'), true)) || /* Carriage return. */ - ((c_next == 'a') && ((void)(c = '\a'), true)) || /* Bell. */ - ((c_next == 'b') && ((void)(c = '\b'), true)) || /* Backspace. */ - ((c_next == 'f') && ((void)(c = '\f'), true))) /* Form-feed. */ - { - i++; - src++; - } + if (UNLIKELY(c == '\\') && (str_unescape_pair(*(src + 1), &c))) { + src++; } - dst[len++] = c; } dst[len] = 0; @@ -491,6 +534,24 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict return result; } +bool BLI_str_quoted_substr(const char *__restrict str, + const char *__restrict prefix, + char *result, + size_t result_maxlen) +{ + int start_match_ofs, end_match_ofs; + if (!BLI_str_quoted_substr_range(str, prefix, &start_match_ofs, &end_match_ofs)) { + return false; + } + const size_t escaped_len = (size_t)(end_match_ofs - start_match_ofs); + bool is_complete; + BLI_str_unescape_ex(result, str + start_match_ofs, escaped_len, result_maxlen, &is_complete); + if (is_complete == false) { + *result = '\0'; + } + return is_complete; +} + /** * string with all instances of substr_old replaced with substr_new, * Returns a copy of the c-string \a str into a newly #MEM_mallocN'd diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index 916d4232f03..97679723d84 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -206,16 +206,17 @@ static void animchan_sync_fcurve_scene(bAnimListElem *ale) BLI_assert(GS(owner_id->name) == ID_SCE); Scene *scene = (Scene *)owner_id; FCurve *fcu = (FCurve *)ale->data; + Sequence *seq = NULL; /* Only affect if F-Curve involves sequence_editor.sequences. */ - char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - if (seq_name == NULL) { + char seq_name[sizeof(seq->name)]; + if (!BLI_str_quoted_substr(fcu->rna_path, "sequences_all[", seq_name, sizeof(seq_name))) { return; } /* Check if this strip is selected. */ Editing *ed = SEQ_editing_get(scene); - Sequence *seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false); + seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false); MEM_freeN(seq_name); if (seq == NULL) { diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 104540e2257..b12e0ae5cab 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1061,13 +1061,14 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id if (GS(owner_id->name) == ID_OB) { Object *ob = (Object *)owner_id; - char *bone_name; + bPoseChannel *pchan = NULL; + char bone_name[sizeof(pchan->name)]; /* Only consider if F-Curve involves `pose.bones`. */ - if (fcu->rna_path && (bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["))) { + if (fcu->rna_path && + BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) { /* Get bone-name, and check if this bone is selected. */ - bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - MEM_freeN(bone_name); + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); /* check whether to continue or skip */ if (pchan && pchan->bone) { @@ -1097,17 +1098,17 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id } else if (GS(owner_id->name) == ID_SCE) { Scene *scene = (Scene *)owner_id; - char *seq_name; + Sequence *seq = NULL; + char seq_name[sizeof(seq->name)]; /* Only consider if F-Curve involves `sequence_editor.sequences`. */ - if (fcu->rna_path && (seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["))) { + if (fcu->rna_path && + BLI_str_quoted_substr(fcu->rna_path, "sequences_all[", seq_name, sizeof(seq_name))) { /* Get strip name, and check if this strip is selected. */ - Sequence *seq = NULL; Editing *ed = SEQ_editing_get(scene); if (ed) { seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false); } - MEM_freeN(seq_name); /* Can only add this F-Curve if it is selected. */ if (ads->filterflag & ADS_FILTER_ONLYSEL) { @@ -1139,14 +1140,14 @@ static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id } else if (GS(owner_id->name) == ID_NT) { bNodeTree *ntree = (bNodeTree *)owner_id; - char *node_name; + bNode *node = NULL; + char node_name[sizeof(node->name)]; /* Check for selected nodes. */ - if (fcu->rna_path && (node_name = BLI_str_quoted_substrN(fcu->rna_path, "nodes["))) { - bNode *node = NULL; + if (fcu->rna_path && + (BLI_str_quoted_substr(fcu->rna_path, "nodes[", node_name, sizeof(node_name)))) { /* Get strip name, and check if this strip is selected. */ node = nodeFindNodebyName(ntree, node_name); - MEM_freeN(node_name); /* Can only add this F-Curve if it is selected. */ if (node) { diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index eda87cf1897..33b4882927a 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -106,23 +106,14 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) * - If a pointer just refers to the ID-block, then don't repeat this info * since this just introduces clutter. */ - if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) { - /* perform string 'chopping' to get "Bone Name : Constraint Name" */ - char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); - char *constName = BLI_str_quoted_substrN(fcu->rna_path, "constraints["); + + char pchanName[256], constName[256]; + if (BLI_str_quoted_substr(fcu->rna_path, "bones[", pchanName, sizeof(pchanName)) && + BLI_str_quoted_substr(fcu->rna_path, "constraints[", constName, sizeof(constName))) { /* assemble the string to display in the UI... */ - structname = BLI_sprintfN( - "%s : %s", pchanName ? pchanName : "", constName ? constName : ""); + structname = BLI_sprintfN("%s : %s", pchanName, constName); free_structname = 1; - - /* free the temp names */ - if (pchanName) { - MEM_freeN(pchanName); - } - if (constName) { - MEM_freeN(constName); - } } else if (ptr.data != ptr.owner_id) { PropertyRNA *nameprop = RNA_struct_name_property(ptr.type); @@ -139,18 +130,15 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) * displaying the struct name alone is no meaningful information (and also cannot be * filtered well), same for modifiers. So display strip name alongside as well. */ if (GS(ptr.owner_id->name) == ID_SCE) { - if (BLI_str_startswith(fcu->rna_path, "sequence_editor.sequences_all[\"")) { + char stripname[256]; + if (BLI_str_quoted_substr( + fcu->rna_path, "sequence_editor.sequences_all[", stripname, sizeof(stripname))) { if (strstr(fcu->rna_path, ".transform.") || strstr(fcu->rna_path, ".crop.") || strstr(fcu->rna_path, ".modifiers[")) { - char *stripname = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - const char *structname_all = BLI_sprintfN( - "%s : %s", stripname ? stripname : "", structname); + const char *structname_all = BLI_sprintfN("%s : %s", stripname, structname); if (free_structname) { MEM_freeN((void *)structname); } - if (stripname) { - MEM_freeN(stripname); - } structname = structname_all; free_structname = 1; } diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 9f3fe239113..ec33a42af3b 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -761,11 +761,10 @@ short copy_animedit_keys(bAnimContext *ac, ListBase *anim_data) if ((aci->id_type == ID_OB) && (((Object *)aci->id)->type == OB_ARMATURE) && aci->rna_path) { Object *ob = (Object *)aci->id; - char *bone_name = BLI_str_quoted_substrN(aci->rna_path, "pose.bones["); - if (bone_name) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - MEM_freeN(bone_name); - + bPoseChannel *pchan; + char bone_name[sizeof(pchan->name)]; + if (BLI_str_quoted_substr(aci->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); if (pchan) { aci->is_bone = true; } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 292d665caca..8dc4aed9f0e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -2218,11 +2218,11 @@ static int clear_anim_v3d_exec(bContext *C, wmOperator *UNUSED(op)) if (ob->mode & OB_MODE_POSE) { if (fcu->rna_path) { /* Get bone-name, and check if this bone is selected. */ - char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - if (bone_name) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - MEM_freeN(bone_name); - + bPoseChannel *pchan = NULL; + char bone_name[sizeof(pchan->name)]; + if (BLI_str_quoted_substr( + fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) { + pchan = BKE_pose_channel_find_name(ob->pose, bone_name); /* Delete if bone is selected. */ if ((pchan) && (pchan->bone)) { if (pchan->bone->flag & BONE_SELECTED) { @@ -2323,13 +2323,11 @@ static int delete_key_v3d_without_keying_set(bContext *C, wmOperator *op) bPoseChannel *pchan = NULL; /* Get bone-name, and check if this bone is selected. */ - char *bone_name = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - if (bone_name == NULL) { + char bone_name[sizeof(pchan->name)]; + if (!BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) { continue; } - pchan = BKE_pose_channel_find_name(ob->pose, bone_name); - MEM_freeN(bone_name); /* skip if bone is not selected */ if ((pchan) && (pchan->bone)) { diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 4db8569a7d2..e5b8983af93 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -1106,12 +1106,12 @@ static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool ex for (ksp = ks->paths.first; ksp; ksp = ksp->next) { /* only items related to this object will be relevant */ if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) { - char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones["); - if (boneName == NULL) { + bPoseChannel *pchan = NULL; + char boneName[sizeof(pchan->name)]; + if (!BLI_str_quoted_substr(ksp->rna_path, "bones[", boneName, sizeof(boneName))) { continue; } - bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName); - MEM_freeN(boneName); + pchan = BKE_pose_channel_find_name(pose, boneName); if (pchan) { /* select if bone is visible and can be affected */ diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 98e00c20170..8f896512410 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -145,15 +145,15 @@ static void autokeyframe_pose( if (act) { for (fcu = act->curves.first; fcu; fcu = fcu->next) { /* only insert keyframes for this F-Curve if it affects the current bone */ - char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); - if (pchanName == NULL) { + char pchan_name[sizeof(pchan->name)]; + if (!BLI_str_quoted_substr(fcu->rna_path, "bones[", pchan_name, sizeof(pchan_name))) { continue; } /* only if bone name matches too... * NOTE: this will do constraints too, but those are ok to do here too? */ - if (STREQ(pchanName, pchan->name)) { + if (STREQ(pchan_name, pchan->name)) { insert_keyframe(bmain, reports, id, @@ -166,8 +166,6 @@ static void autokeyframe_pose( &nla_cache, flag); } - - MEM_freeN(pchanName); } } } diff --git a/source/blender/io/collada/BCAnimationCurve.cpp b/source/blender/io/collada/BCAnimationCurve.cpp index 82d8b6e9ff3..005197c9027 100644 --- a/source/blender/io/collada/BCAnimationCurve.cpp +++ b/source/blender/io/collada/BCAnimationCurve.cpp @@ -173,10 +173,9 @@ std::string BCAnimationCurve::get_animation_name(Object *ob) const name = ""; } else { - char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones["); - if (boneName) { + char boneName[MAXBONENAME]; + if (BLI_str_quoted_substr(fcurve->rna_path, "pose.bones[", boneName, sizeof(boneName))) { name = id_name(ob) + "_" + std::string(boneName); - MEM_freeN(boneName); } else { name = ""; diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index d2bde193c0a..953af5adffc 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -447,10 +447,9 @@ void BCAnimationSampler::initialize_curves(BCAnimationCurveMap &curves, Object * for (; fcu; fcu = fcu->next) { object_type = BC_ANIMATION_TYPE_OBJECT; if (ob->type == OB_ARMATURE) { - char *boneName = BLI_str_quoted_substrN(fcu->rna_path, "pose.bones["); - if (boneName) { + char boneName[MAXBONENAME]; + if (BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", boneName, sizeof(boneName))) { object_type = BC_ANIMATION_TYPE_BONE; - MEM_freeN(boneName); } } |