1e8556ba3Sopenharmony_ci"""Utility functions not closely tied to other spec_tools types."""
2e8556ba3Sopenharmony_ci# Copyright (c) 2018-2019 Collabora, Ltd.
3e8556ba3Sopenharmony_ci# Copyright 2013-2024 The Khronos Group Inc.
4e8556ba3Sopenharmony_ci# SPDX-License-Identifier: Apache-2.0
5e8556ba3Sopenharmony_ci
6e8556ba3Sopenharmony_ci
7e8556ba3Sopenharmony_cidef getElemName(elem, default=None):
8e8556ba3Sopenharmony_ci    """Get the name associated with an element, either a name child or name attribute."""
9e8556ba3Sopenharmony_ci    name_elem = elem.find('name')
10e8556ba3Sopenharmony_ci    if name_elem is not None:
11e8556ba3Sopenharmony_ci        return name_elem.text
12e8556ba3Sopenharmony_ci    # Fallback if there is no child.
13e8556ba3Sopenharmony_ci    return elem.get('name', default)
14e8556ba3Sopenharmony_ci
15e8556ba3Sopenharmony_ci
16e8556ba3Sopenharmony_cidef getElemType(elem, default=None):
17e8556ba3Sopenharmony_ci    """Get the type associated with an element, either a type child or type attribute."""
18e8556ba3Sopenharmony_ci    type_elem = elem.find('type')
19e8556ba3Sopenharmony_ci    if type_elem is not None:
20e8556ba3Sopenharmony_ci        return type_elem.text
21e8556ba3Sopenharmony_ci    # Fallback if there is no child.
22e8556ba3Sopenharmony_ci    return elem.get('type', default)
23e8556ba3Sopenharmony_ci
24e8556ba3Sopenharmony_ci
25e8556ba3Sopenharmony_cidef findFirstWithPredicate(collection, pred):
26e8556ba3Sopenharmony_ci    """Return the first element that satisfies the predicate, or None if none exist.
27e8556ba3Sopenharmony_ci
28e8556ba3Sopenharmony_ci    NOTE: Some places where this is used might be better served by changing to a dictionary.
29e8556ba3Sopenharmony_ci    """
30e8556ba3Sopenharmony_ci    for elt in collection:
31e8556ba3Sopenharmony_ci        if pred(elt):
32e8556ba3Sopenharmony_ci            return elt
33e8556ba3Sopenharmony_ci    return None
34e8556ba3Sopenharmony_ci
35e8556ba3Sopenharmony_ci
36e8556ba3Sopenharmony_cidef findNamedElem(elems, name):
37e8556ba3Sopenharmony_ci    """Traverse a collection of elements with 'name' nodes or attributes, looking for and returning one with the right name.
38e8556ba3Sopenharmony_ci
39e8556ba3Sopenharmony_ci    NOTE: Many places where this is used might be better served by changing to a dictionary.
40e8556ba3Sopenharmony_ci    """
41e8556ba3Sopenharmony_ci    return findFirstWithPredicate(elems, lambda elem: getElemName(elem) == name)
42e8556ba3Sopenharmony_ci
43e8556ba3Sopenharmony_ci
44e8556ba3Sopenharmony_cidef findTypedElem(elems, typename):
45e8556ba3Sopenharmony_ci    """Traverse a collection of elements with 'type' nodes or attributes, looking for and returning one with the right typename.
46e8556ba3Sopenharmony_ci
47e8556ba3Sopenharmony_ci    NOTE: Many places where this is used might be better served by changing to a dictionary.
48e8556ba3Sopenharmony_ci    """
49e8556ba3Sopenharmony_ci    return findFirstWithPredicate(elems, lambda elem: getElemType(elem) == typename)
50e8556ba3Sopenharmony_ci
51e8556ba3Sopenharmony_ci
52e8556ba3Sopenharmony_cidef findNamedObject(collection, name):
53e8556ba3Sopenharmony_ci    """Traverse a collection of elements with 'name' attributes, looking for and returning one with the right name.
54e8556ba3Sopenharmony_ci
55e8556ba3Sopenharmony_ci    NOTE: Many places where this is used might be better served by changing to a dictionary.
56e8556ba3Sopenharmony_ci    """
57e8556ba3Sopenharmony_ci    return findFirstWithPredicate(collection, lambda elt: elt.name == name)
58