1# Synthetic children provider example for class MaskedData
2# to use me:
3# command script import ./example.py --allow-reload
4# type synthetic add MaskedData --python-class
5# example.MaskedData_SyntheticChildrenProvider
6
7
8class MaskedData_SyntheticChildrenProvider:
9
10    def __init__(self, valobj, dict):
11        # remember the SBValue since you will not have another chance to get it
12        # :-)
13        self.valobj = valobj
14
15    def num_children(self):
16        # you could perform calculations involving the SBValue and/or its children to determine this value
17        # here, we have an hardcoded value - but since you have stored the SBValue you could use it to
18        # help figure out the correct thing to return here. if you return a number N, you should be prepared to
19        # answer questions about N children
20        return 4
21
22    def has_children(self):
23        # we simply say True here because we know we have 4 children
24        # in general, you want to make this calculation as simple as possible
25        # and return True if in doubt (you can always return num_children == 0
26        # later)
27        return True
28
29    def get_child_index(self, name):
30        # given a name, return its index
31        # you can return None if you don't know the answer for a given name
32        if name == "value":
33            return 0
34        # here, we are using a reserved C++ keyword as a child name - we could not do that in the source code
35        # but we are free to use the names we like best in the synthetic children provider class
36        # we are also not respecting the order of declaration in the C++ class itself - as long as
37        # we are consistent, we can do that freely
38        if name == "operator":
39            return 1
40        if name == "mask":
41            return 2
42        # this member does not exist in the original class - we will compute its value and show it to the user
43        # when returning synthetic children, there is no need to only stick to
44        # what already exists in memory
45        if name == "apply()":
46            return 3
47        return None  # no clue, just say none
48
49    def get_child_at_index(self, index):
50        # precautionary measures
51        if index < 0:
52            return None
53        if index > self.num_children():
54            return None
55        if self.valobj.IsValid() == False:
56            return None
57        if index == 0:
58            return self.valobj.GetChildMemberWithName("value")
59        if index == 1:
60            # fetch the value of the operator
61            op_chosen = self.valobj.GetChildMemberWithName(
62                "oper").GetValueAsUnsigned()
63            # if it is a known value, return a descriptive string for it
64            # we are not doing this in the most efficient possible way, but the code is very readable
65            # and easy to maintain - if you change the values on the C++ side,
66            # the same changes must be made here
67            if op_chosen == 0:
68                return self.valobj.CreateValueFromExpression(
69                    "operator", '(const char*)"none"')
70            elif op_chosen == 1:
71                return self.valobj.CreateValueFromExpression(
72                    "operator", '(const char*)"AND"')
73            elif op_chosen == 2:
74                return self.valobj.CreateValueFromExpression(
75                    "operator", '(const char*)"OR"')
76            elif op_chosen == 3:
77                return self.valobj.CreateValueFromExpression(
78                    "operator", '(const char*)"XOR"')
79            elif op_chosen == 4:
80                return self.valobj.CreateValueFromExpression(
81                    "operator", '(const char*)"NAND"')
82            elif op_chosen == 5:
83                return self.valobj.CreateValueFromExpression(
84                    "operator", '(const char*)"NOR"')
85            else:
86                return self.valobj.CreateValueFromExpression(
87                    "operator", '(const char*)"unknown"')  # something else
88        if index == 2:
89            return self.valobj.GetChildMemberWithName("mask")
90        if index == 3:
91            # for this, we must fetch all the other elements
92            # in an efficient implementation, we would be caching this data for
93            # efficiency
94            value = self.valobj.GetChildMemberWithName(
95                "value").GetValueAsUnsigned()
96            operator = self.valobj.GetChildMemberWithName(
97                "oper").GetValueAsUnsigned()
98            mask = self.valobj.GetChildMemberWithName(
99                "mask").GetValueAsUnsigned()
100            # compute the masked value according to the operator
101            if operator == 1:
102                value = value & mask
103            elif operator == 2:
104                value = value | mask
105            elif operator == 3:
106                value = value ^ mask
107            elif operator == 4:
108                value = ~(value & mask)
109            elif operator == 5:
110                value = ~(value | mask)
111            else:
112                pass
113            value &= 0xFFFFFFFF  # make sure Python does not extend our values to 64-bits
114            # return it - again, not the most efficient possible way. we should actually be pushing the computed value
115            # into an SBData, and using the SBData to create an SBValue - this
116            # has the advantage of readability
117            return self.valobj.CreateValueFromExpression(
118                "apply()", '(uint32_t)(' + str(value) + ')')
119
120    def update(self):
121        # we do not do anything special in update - but this would be the right place to lookup
122        # the data we use in get_child_at_index and cache it
123        pass
124