Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-09-04 07:22:44 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-09-04 09:59:54 +0300
commite6194e735791b42feb51e810a4910a41d999d3bf (patch)
tree95889982ba8c6bc88f5bdfb2eded77159d81ca89 /source/blender/blenlib
parent716682365c6bcc1b5f757232ce1d2499b0d062a9 (diff)
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.
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r--source/blender/blenlib/BLI_string.h12
-rw-r--r--source/blender/blenlib/intern/string.c97
2 files changed, 90 insertions, 19 deletions
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