[Bf-blender-cvs] [f1cdd49a4e7] master: BLI_string: add BLI_str_quoted_substr_range

Campbell Barton noreply at git.blender.org
Wed Sep 1 07:33:42 CEST 2021


Commit: f1cdd49a4e7fb2883d574691eab16b2ffc1f52a3
Author: Campbell Barton
Date:   Wed Sep 1 15:23:58 2021 +1000
Branches: master
https://developer.blender.org/rBf1cdd49a4e7fb2883d574691eab16b2ffc1f52a3

BLI_string: add BLI_str_quoted_substr_range

This is a similar funciton to BLI_str_quoted_substrN
that extracts the range of the quoted string
instead of allocating a new string un-escaped string.

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

M	source/blender/blenlib/BLI_string.h
M	source/blender/blenlib/intern/string.c

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

diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 0c51d38e813..c20376c42b9 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -57,6 +57,11 @@ size_t BLI_strncpy_rlen(char *__restrict dst,
 size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
 
+bool BLI_str_quoted_substr_range(const char *__restrict str,
+                                 const char *__restrict prefix,
+                                 int *__restrict r_start,
+                                 int *__restrict r_end) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL(1, 2, 3, 4);
 char *BLI_str_quoted_substrN(const char *__restrict str,
                              const char *__restrict prefix) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL() ATTR_MALLOC;
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 5541d75bc73..0be8700810e 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -419,6 +419,53 @@ const char *BLI_str_escape_find_quote(const char *str)
   return (*str == '"') ? str : NULL;
 }
 
+/**
+ * Return the range of the quoted string (excluding quotes) `str` after `prefix`.
+ *
+ * A version of #BLI_str_quoted_substrN that calculates the range
+ * instead of un-escaping and allocating the result.
+ *
+ * \param str: String potentially including `prefix`.
+ * \param prefix: Quoted string prefix.
+ * \param r_start: The start of the quoted string (after the first quote).
+ * \param r_end: The end of the quoted string (before the last quote).
+ * \return True when a quoted string range could be found after `prefix`.
+ */
+bool BLI_str_quoted_substr_range(const char *__restrict str,
+                                 const char *__restrict prefix,
+                                 int *__restrict r_start,
+                                 int *__restrict r_end)
+{
+  const char *str_start = strstr(str, prefix);
+  if (str_start == NULL) {
+    return false;
+  }
+  const size_t prefix_len = strlen(prefix);
+  if (UNLIKELY(prefix_len == 0)) {
+    BLI_assert_msg(0,
+                   "Zero length prefix passed in, "
+                   "caller must prevent this from happening!");
+    return false;
+  }
+  BLI_assert_msg(prefix[prefix_len - 1] != '"',
+                 "Prefix includes trailing quote, "
+                 "caller must prevent this from happening!");
+
+  str_start += prefix_len;
+  if (UNLIKELY(*str_start != '\"')) {
+    return false;
+  }
+  str_start += 1;
+  const char *str_end = BLI_str_escape_find_quote(str_start);
+  if (UNLIKELY(str_end == NULL)) {
+    return false;
+  }
+
+  *r_start = (int)(str_start - str);
+  *r_end = (int)(str_end - str);
+  return true;
+}
+
 /**
  * Makes a copy of the text within the "" that appear after some text `blahblah`.
  * i.e. for string `pose["apples"]` with prefix `pose[`, it will return `apples`.
@@ -431,27 +478,17 @@ const char *BLI_str_escape_find_quote(const char *str)
  */
 char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix)
 {
-  const char *start_match, *end_match;
-
-  /* get the starting point (i.e. where prefix starts, and add prefix_len+1
-   * to it to get be after the first " */
-  start_match = strstr(str, prefix);
-  if (start_match) {
-    const size_t prefix_len = strlen(prefix);
-    start_match += prefix_len + 1;
-    /* get the end point (i.e. where the next occurrence of " is after the starting point) */
-    end_match = BLI_str_escape_find_quote(start_match);
-    if (end_match) {
-      const size_t escaped_len = (size_t)(end_match - start_match);
-      char *result = MEM_mallocN(sizeof(char) * (escaped_len + 1), __func__);
-      const size_t unescaped_len = BLI_str_unescape(result, start_match, escaped_len);
-      if (unescaped_len != escaped_len) {
-        result = MEM_reallocN(result, sizeof(char) * (unescaped_len + 1));
-      }
-      return result;
-    }
+  int start_match_ofs, end_match_ofs;
+  if (!BLI_str_quoted_substr_range(str, prefix, &start_match_ofs, &end_match_ofs)) {
+    return NULL;
+  }
+  const size_t escaped_len = (size_t)(end_match_ofs - start_match_ofs);
+  char *result = MEM_mallocN(sizeof(char) * (escaped_len + 1), __func__);
+  const size_t unescaped_len = BLI_str_unescape(result, str + start_match_ofs, escaped_len);
+  if (unescaped_len != escaped_len) {
+    result = MEM_reallocN(result, sizeof(char) * (unescaped_len + 1));
   }
-  return NULL;
+  return result;
 }
 
 /**



More information about the Bf-blender-cvs mailing list