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