[Bf-blender-cvs] [e6194e73579] master: RNA: support extracting names from paths without allocating memory

Campbell Barton noreply at git.blender.org
Sat Sep 4 09:01:13 CEST 2021


Commit: e6194e735791b42feb51e810a4910a41d999d3bf
Author: Campbell Barton
Date:   Sat Sep 4 14:22:44 2021 +1000
Branches: master
https://developer.blender.org/rBe6194e735791b42feb51e810a4910a41d999d3bf

RNA: support extracting names from paths without allocating memory

Support extracting identifiers RNA paths into fixed size buffer
since the maximum size of the identifier is known all cases.

- Add BLI_str_unescape_ex to support limiting the destination buffer.
- Add BLI_str_quoted_substr to copy values into a fixed size buffer.

===================================================================

M	source/blender/blenkernel/intern/action_bones.cc
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/blenlib/BLI_string.h
M	source/blender/blenlib/intern/string.c
M	source/blender/editors/animation/anim_deps.c
M	source/blender/editors/animation/anim_filter.c
M	source/blender/editors/animation/anim_ipo_utils.c
M	source/blender/editors/animation/keyframes_general.c
M	source/blender/editors/animation/keyframing.c
M	source/blender/editors/armature/pose_select.c
M	source/blender/editors/transform/transform_convert_armature.c
M	source/blender/io/collada/BCAnimationCurve.cpp
M	source/blender/io/collada/BCAnimationSampler.cpp

===================================================================

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/blende

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list