diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-09-01 08:23:58 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-09-01 08:23:58 +0300 |
commit | f1cdd49a4e7fb2883d574691eab16b2ffc1f52a3 (patch) | |
tree | 1d3af334b7ef5f70c1fdfb051cc28ece7eb1bdd0 /source/blender | |
parent | 90dac47717b12f33d5dd738da12a337cfe4f2f14 (diff) |
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.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenlib/BLI_string.h | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string.c | 77 |
2 files changed, 62 insertions, 20 deletions
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 @@ -420,6 +420,53 @@ const char *BLI_str_escape_find_quote(const char *str) } /** + * 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; } /** |