ValueTree::findChildrenLike()


#1

Hi,

First, I’d like to thank you for these very wonderful classes.

I think such a method should be added to the value tree, as it’s often found in our code:

/** Check if this item could match the other's one.
     Only the top level type and properties are checked.
     This returns true even if the other's one have less properties than us, unless exactProperties is true. */
bool ValueTree::couldMatch(const ValueTree & other, bool exactProperties)
{
    if (other.getType() != getType()) return false;
    if (exactProperties && other.getNumProperties() != getNumProperties()) return false;
    for (int i = 0; i < other.getNumProperties(); i++)
        if (!hasProperty(other.getPropertyName(i)) || getProperty(other.getPropertyName(i)) != other.getProperty(other.getPropertyName(i))) return false;
    return true;
}

/** Try to locate a child that could match the given template. 
     This search can be recursive if told to, and the exact properties can be checked too. 
     If no child is found, an invalid tree is returned. */
ValueTree ValueTree::findChildLike(const ValueTree & other, bool exactProperties, bool recursive)
{
    int index = 0;    
    while (getChild(index).isValid())
    {
         ValueTree item = getChild(index); 
         if (item.couldMatch(other, exactProperties)) return item;
         else if (recursive)
         {
              ValueTree child = item.findChildLike(other, exactProperties, recursive); 
              if (child.isValid()) return child;
         }
         index++;
    }
    return ValueTree::invalid;
}

#2

Nah, don’t really like those. And it’s not immediately obvious to me what it actually does!

I’ve got to be pretty strict about adding member functions to core classes like ValueTree, so for a new member function, it’d need to be either:
a) something that can’t be done by an external function
b) or is very commonly used

…and these don’t really fit either of those criteria. Since you could implement it just as well using an external function, it’d be best to do it that way.


#3

Well, when your value tree is large, and you want to access a specific child, you always kind of search for it.
This search code is very often found (even in the jucer, you have plenty of examples).
This method simply add a search for a specific child, and this is done by first creating a “pseudo” value tree, with the property and name you want, and let the function find the first child that is similar to your example child in your source tree.

It’s a real time saver, and as always, when a method is done once and working, don’t let user reinvent the wheel and probably do it wrong.


#4

You might want to have a look at the ValueTree searching framework I created a little while ago (forum link). It’s a set of classes which implement an algorithm based on the approach used by XPath. You can use them to create your own ValueTree searching systems quite easily; you just need to define the criteria used. [I provided an example that uses text strings to illustrate how it can work]


#5

Yes it’s a nice piece of code you’ve made.

However, while I haven’t dig much in your source, I liked the idea of “Find by example/template” of my code.
You can probably do this in a Xpath like manner (//child[prop1=“oijoj” and prop2=“oijoij”]) but I haven’t seen how to do “and” in your basic finder, I’ve probably missed it.

Still, this version is clearly very simple and, thus, no parsing so it’s very very fast (as fast as it can be).


#6

It’s all in how you define the various steps; the string path-based sample you refer to is just an example layer to demonstrate one method of searching (the method I needed at the time - using a path) but you could easily make something that selects nodes based on an example as you describe. The finder mechanism doesn’t do any parsing at all. Its not an implementation of xpath, the algorithm is just based on the approach it uses.

I would ignore the ‘basic finder’ part completely (except perhaps for demonstration purposes), and look at the classes they derive from; it’s all about selecting a set of nodes and filtering the results - no parsing of strings or anything. Scouring a tree for any kind of pattern is quite a complex job, and the base classes take care of most of the hard work for you.


#7

Sorry, I completely missed the bit where you present code that already works for you! :slight_smile: I skim-read it as something you wanted to implement.

Still, doesn’t help to keep the word out should anyone else have more complex searching needs :slight_smile: