Cleanup for RNA_path_resolve_full.

* Moved collection key parsing and array index parsing into their own
functions, to make the main path loop easier to follow.
* Unified boolean return values.
This commit is contained in:
Lukas Tönne 2014-03-10 12:22:47 +01:00
parent 4d47e75223
commit fe094eaf20

@ -3902,98 +3902,42 @@ bool RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, Prop
return RNA_path_resolve_full(ptr, path, r_ptr, r_prop, NULL);
}
/* Resolve the given RNA Path to find the pointer and/or property + array index indicated by fully resolving the path
* ! Assumes all pointers provided are valid
* > returns: True if path can be resolved to a valid "pointer + property" OR "pointer only"
*/
bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *index)
static bool path_resolve_collection_key(const char **path, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_nextptr)
{
PropertyRNA *prop;
PointerRNA curptr;
PointerRNA nextptr; /* keep uninitialized, helps expose bugs in collection accessor functions */
char fixedbuf[256], *token;
int type, intkey;
int intkey;
prop = NULL;
curptr = *ptr;
/* end of path, ok */
if (!(**path))
return true;
if (path == NULL || *path == '\0')
return 0;
while (*path) {
int use_id_prop = (*path == '[') ? 1 : 0;
/* custom property lookup ?
* C.object["someprop"]
*/
/* look up property name in current struct */
token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
if (!token)
return 0;
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);
}
else {
prop = RNA_struct_find_property(&curptr, token);
}
if (token != fixedbuf)
MEM_freeN(token);
if (!prop)
return 0;
type = RNA_property_type(prop);
/* now look up the value of this property if it is a pointer or
* collection, otherwise return the property rna so that the
* caller can read the value of the property itself */
switch (type) {
case PROP_POINTER:
nextptr = RNA_property_pointer_get(&curptr, prop);
if (nextptr.data) {
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
if (index) *index = -1;
}
else
return 0;
break;
case PROP_COLLECTION:
if (*path) {
if (*path == '[') {
if (**path == '[') {
/* resolve the lookup with [] brackets */
token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
if (!token)
return 0;
return false;
/* check for "" to see if it is a string */
if (rna_token_strip_quotes(token)) {
if (RNA_property_collection_lookup_string(&curptr, prop, token + 1, &nextptr)) {
if (RNA_property_collection_lookup_string(ptr, prop, token + 1, r_nextptr)) {
/* pass */
}
else {
nextptr.data = NULL;
r_nextptr->data = NULL;
}
}
else {
/* otherwise do int lookup */
intkey = atoi(token);
if (intkey == 0 && (token[0] != '0' || token[1] != '\0')) {
return 0; /* we can be sure the fixedbuf was used in this case */
return false; /* we can be sure the fixedbuf was used in this case */
}
if (RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr)) {
if (RNA_property_collection_lookup_int(ptr, prop, intkey, r_nextptr)) {
/* pass */
}
else {
nextptr.data = NULL;
r_nextptr->data = NULL;
}
}
@ -4002,49 +3946,42 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
}
}
else {
PointerRNA c_ptr;
if (RNA_property_collection_type_get(&curptr, prop, &c_ptr)) {
nextptr = c_ptr;
if (RNA_property_collection_type_get(ptr, prop, r_nextptr)) {
/* pass */
}
else {
/* ensure we quit on invalid values */
nextptr.data = NULL;
r_nextptr->data = NULL;
}
}
if (nextptr.data) {
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
if (index) *index = -1;
}
else
return 0;
return r_nextptr->data != NULL;
}
break;
default:
if (index == NULL)
break;
*index = -1;
if (*path) {
static bool path_resolve_array_index(const char **path, PointerRNA *ptr, PropertyRNA *prop, int *r_index)
{
char fixedbuf[256], *token;
int index_arr[RNA_MAX_ARRAY_DIMENSION] = {0};
int len[RNA_MAX_ARRAY_DIMENSION];
const int dim = RNA_property_array_dimension(&curptr, prop, len);
int i, temp_index;
const int dim = RNA_property_array_dimension(ptr, prop, len);
int i;
*r_index = -1;
/* end of path, ok */
if (!(**path))
return true;
for (i = 0; i < dim; i++) {
temp_index = -1;
int temp_index = -1;
/* multi index resolve */
if (*path == '[') {
token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
if (**path == '[') {
token = rna_path_token(path, fixedbuf, sizeof(fixedbuf), 1);
if (token == NULL) {
/* invalid syntax blah[] */
return 0;
return false;
}
/* check for "" to see if it is a string */
else if (rna_token_strip_quotes(token)) {
@ -4059,16 +3996,16 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
MEM_freeN(token);
}
return 0;
return false;
}
}
}
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), 0);
if (token == NULL) {
/* invalid syntax blah.. */
return 0;
return false;
}
temp_index = RNA_property_array_item_index(prop, *token);
}
@ -4079,17 +4016,18 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
/* out of range */
if (temp_index < 0 || temp_index >= len[i])
return 0;
return false;
index_arr[i] = temp_index;
/* end multi index resolve */
}
/* arrays always contain numbers so further values are not valid */
if (*path) {
return 0;
}
else {
if (**path)
return false;
/* flatten index over all dimensions */
{
int totdim = 1;
int flat_index = 0;
@ -4098,16 +4036,92 @@ bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr,
totdim *= len[i];
}
*index = flat_index;
*r_index = flat_index;
}
return true;
}
/* Resolve the given RNA Path to find the pointer and/or property + array index indicated by fully resolving the path
* ! Assumes all pointers provided are valid
* > returns: True if path can be resolved to a valid "pointer + property" OR "pointer only"
*/
bool RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *index)
{
PropertyRNA *prop;
PointerRNA curptr;
PointerRNA nextptr; /* keep uninitialized, helps expose bugs in collection accessor functions */
char fixedbuf[256], *token;
int type;
prop = NULL;
curptr = *ptr;
if (path == NULL || *path == '\0')
return false;
while (*path) {
int use_id_prop = (*path == '[') ? 1 : 0;
/* custom property lookup ?
* C.object["someprop"]
*/
/* look up property name in current struct */
token = rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
if (!token)
return false;
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);
}
else {
prop = RNA_struct_find_property(&curptr, token);
}
if (token != fixedbuf)
MEM_freeN(token);
if (!prop)
return false;
type = RNA_property_type(prop);
/* now look up the value of this property if it is a pointer or
* collection, otherwise return the property rna so that the
* caller can read the value of the property itself */
switch (type) {
case PROP_POINTER:
nextptr = RNA_property_pointer_get(&curptr, prop);
if (nextptr.data == NULL)
return false;
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
if (index) *index = -1;
break;
case PROP_COLLECTION:
if (!path_resolve_collection_key(&path, &curptr, prop, &nextptr))
return false;
curptr = nextptr;
prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
if (index) *index = -1;
break;
default:
if (index) {
if (!path_resolve_array_index(&path, &curptr, prop, index))
return false;
}
break;
}
}
*r_ptr = curptr;
*r_prop = prop;
return 1;
return true;
}