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:
Diffstat (limited to 'source/blender/makesrna/intern/rna_access.c')
-rw-r--r--source/blender/makesrna/intern/rna_access.c187
1 files changed, 118 insertions, 69 deletions
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 51e20eb9e7f..0ba5b786187 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4859,75 +4859,119 @@ PointerRNA rna_array_lookup_int(
/* RNA Path - Experiment */
-static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
+/**
+ * Extract the first token from `path`.
+ *
+ * \param path: Extract the token from path, step the pointer to the beginning of the next token
+ * \return The nil terminated token.
+ */
+static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen)
{
- const char *p;
int len = 0;
- if (bracket) {
- /* get data between [], check escaping quotes and back-slashes with #BLI_str_unescape. */
- if (**path == '[') {
- (*path)++;
- }
- else {
- return NULL;
- }
+ /* Get data until `.` or `[`. */
+ const char *p = *path;
+ while (*p && !ELEM(*p, '.', '[')) {
+ len++;
+ p++;
+ }
- p = *path;
+ /* Empty, return. */
+ if (UNLIKELY(len == 0)) {
+ return NULL;
+ }
- /* 2 kinds of look-ups now, quoted or unquoted. */
- if (*p != '"') {
- while (*p && (*p != ']')) {
- len++;
- p++;
- }
- }
- else {
- const char *p_end = BLI_str_escape_find_quote(p + 1);
- if (p_end == NULL) {
- /* No Matching quote. */
- return NULL;
- }
- /* Skip the last quoted char to get the `]`. */
- p_end += 1;
+ /* Try to use fixed buffer if possible. */
+ char *buf = (len + 1 < fixedlen) ? fixedbuf : MEM_mallocN(sizeof(char) * (len + 1), __func__);
+ memcpy(buf, *path, sizeof(char) * len);
+ buf[len] = '\0';
- len += (p_end - p);
- p = p_end;
- }
+ if (*p == '.') {
+ p++;
+ }
+ *path = p;
- if (*p != ']') {
+ return buf;
+}
+
+/**
+ * Extract the first token in brackets from `path` (with quoted text support).
+ *
+ * - `[0]` -> `0`
+ * - `["Some\"Quote"]` -> `Some"Quote`
+ *
+ * \param path: Extract the token from path, step the pointer to the beginning of the next token
+ * (past quoted text and brackets).
+ * \return The nil terminated token.
+ */
+static char *rna_path_token_in_brackets(const char **path,
+ char *fixedbuf,
+ int fixedlen,
+ bool *r_quoted)
+{
+ int len = 0;
+ bool quoted = false;
+
+ BLI_assert(r_quoted != NULL);
+
+ /* Get data between `[]`, check escaping quotes and back-slashes with #BLI_str_unescape. */
+ if (UNLIKELY(**path != '[')) {
+ return NULL;
+ }
+
+ (*path)++;
+ const char *p = *path;
+
+ /* 2 kinds of look-ups now, quoted or unquoted. */
+ if (*p == '"') {
+ /* Find the matching quote. */
+ (*path)++;
+ p = *path;
+ const char *p_end = BLI_str_escape_find_quote(p);
+ if (p_end == NULL) {
+ /* No Matching quote. */
return NULL;
}
+ /* Exclude the last quote from the length. */
+ len += (p_end - p);
+
+ /* Skip the last quoted char to get the `]`. */
+ p_end += 1;
+ p = p_end;
+ quoted = true;
}
else {
- /* Get data until `.` or `[`. */
- p = *path;
-
- while (*p && *p != '.' && *p != '[') {
+ /* Find the matching bracket. */
+ while (*p && (*p != ']')) {
len++;
p++;
}
}
- /* empty, return */
- if (len == 0) {
+ if (UNLIKELY(*p != ']')) {
+ return NULL;
+ }
+
+ /* Empty, return. */
+ if (UNLIKELY(len == 0)) {
return NULL;
}
/* Try to use fixed buffer if possible. */
char *buf = (len + 1 < fixedlen) ? fixedbuf : MEM_mallocN(sizeof(char) * (len + 1), __func__);
- /* copy string, taking into account escaped ] */
- if (bracket) {
+ /* Copy string, taking into account escaped ']' */
+ if (quoted) {
BLI_str_unescape(buf, *path, len);
- p = (*path) + len;
+ /* +1 to step over the last quote. */
+ BLI_assert((*path)[len] == '"');
+ p = (*path) + len + 1;
}
else {
memcpy(buf, *path, sizeof(char) * len);
buf[len] = '\0';
}
-
- /* set path to start of next token */
+ /* Set path to start of next token. */
if (*p == ']') {
p++;
}
@@ -4936,20 +4980,9 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
}
*path = p;
- return buf;
-}
+ *r_quoted = quoted;
-static int rna_token_strip_quotes(char *token)
-{
- if (token[0] == '"') {
- int len = strlen(token);
- if (len >= 2 && token[len - 1] == '"') {
- /* strip away "" */
- token[len - 1] = '\0';
- return 1;
- }
- }
- return 0;
+ return buf;
}
static bool rna_path_parse_collection_key(const char **path,
@@ -4968,18 +5001,19 @@ static bool rna_path_parse_collection_key(const char **path,
}
if (**path == '[') {
+ bool quoted;
char *token;
/* resolve the lookup with [] brackets */
- token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
+ token = rna_path_token_in_brackets(path, fixedbuf, sizeof(fixedbuf), &quoted);
if (!token) {
return false;
}
/* check for "" to see if it is a string */
- if (rna_token_strip_quotes(token)) {
- if (RNA_property_collection_lookup_string(ptr, prop, token + 1, r_nextptr)) {
+ if (quoted) {
+ if (RNA_property_collection_lookup_string(ptr, prop, token, r_nextptr)) {
/* pass */
}
else {
@@ -5041,15 +5075,16 @@ static bool rna_path_parse_array_index(const char **path,
/* multi index resolve */
if (**path == '[') {
- token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
+ bool quoted;
+ token = rna_path_token_in_brackets(path, fixedbuf, sizeof(fixedbuf), &quoted);
if (token == NULL) {
/* invalid syntax blah[] */
return false;
}
/* check for "" to see if it is a string */
- if (rna_token_strip_quotes(token)) {
- temp_index = RNA_property_array_item_index(prop, *(token + 1));
+ if (quoted) {
+ temp_index = RNA_property_array_item_index(prop, *token);
}
else {
/* otherwise do int lookup */
@@ -5066,7 +5101,7 @@ static bool rna_path_parse_array_index(const char **path,
}
else if (dim == 1) {
/* location.x || scale.X, single dimension arrays only */
- token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 0);
+ token = rna_path_token(path, fixedbuf, sizeof(fixedbuf));
if (token == NULL) {
/* invalid syntax blah. */
return false;
@@ -5166,8 +5201,7 @@ static bool rna_path_parse(PointerRNA *ptr,
RNA_POINTER_INVALIDATE(&nextptr);
}
- int use_id_prop = (*path == '[') ? 1 : 0;
- char *token;
+ const bool use_id_prop = (*path == '[');
/* custom property lookup ?
* C.object["someprop"]
*/
@@ -5177,8 +5211,10 @@ static bool rna_path_parse(PointerRNA *ptr,
}
/* look up property name in current struct */
- token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
-
+ bool quoted = false;
+ char *token = use_id_prop ?
+ rna_path_token_in_brackets(&path, fixedbuf, sizeof(fixedbuf), &quoted) :
+ rna_path_token(&path, fixedbuf, sizeof(fixedbuf));
if (!token) {
return false;
}
@@ -5186,8 +5222,8 @@ static bool rna_path_parse(PointerRNA *ptr,
prop = NULL;
if (use_id_prop) { /* look up property name in current struct */
IDProperty *group = RNA_struct_idprops(&curptr, 0);
- if (group && rna_token_strip_quotes(token)) {
- prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, token + 1);
+ if (group && quoted) {
+ prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, token);
}
}
else {
@@ -5326,6 +5362,18 @@ bool RNA_path_resolve_full(
}
/**
+ * A version of #RNA_path_resolve_full doesn't check the value of #PointerRNA.data.
+ *
+ * \note While it's correct to ignore the value of #PointerRNA.data
+ * most callers need to know if the resulting pointer was found and not null.
+ */
+bool RNA_path_resolve_full_maybe_null(
+ PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
+{
+ return rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, true);
+}
+
+/**
* Resolve the given RNA Path to find both the pointer AND property
* indicated by fully resolving the path.
*
@@ -5492,7 +5540,7 @@ char *RNA_path_back(const char *path)
while (*current) {
char *token;
- token = rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
+ token = rna_path_token(&current, fixedbuf, sizeof(fixedbuf));
if (!token) {
return NULL;
@@ -5502,7 +5550,8 @@ char *RNA_path_back(const char *path)
}
/* in case of collection we also need to strip off [] */
- token = rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
+ bool quoted;
+ token = rna_path_token_in_brackets(&current, fixedbuf, sizeof(fixedbuf), &quoted);
if (token && token != fixedbuf) {
MEM_freeN(token);
}