sdbus++: Handle parsing of multi-level containers
The type array contructed by YAML is difficult to process recursively.
So the type array gets preprocessed and converted to a recursive data
structure.
Fixes openbmc/sdbusplus#4
Change-Id: Ife8a47d9b6babd75835f496702ca5899ac6e18c3
Signed-off-by: Christian Andersen <c.andersen@kostal.com>
diff --git a/tools/sdbusplus/property.py b/tools/sdbusplus/property.py
index fed9782..3a0bf23 100644
--- a/tools/sdbusplus/property.py
+++ b/tools/sdbusplus/property.py
@@ -65,14 +65,39 @@
and then wrap it in a [ ] and it becomes valid YAML. (assuming
the user gave us a valid typename)
"""
- parse = yaml.safe_load("[" + ",[".join(typeName.split("[")) + "]")
- return self.__parse_cpp_type__(parse)
+ typeArray = yaml.safe_load("[" + ",[".join(typeName.split("[")) + "]")
+ typeTuple = self.__preprocess_yaml_type_array(typeArray).pop(0)
+ return self.__parse_cpp_type__(typeTuple)
+
+ """ Take a list of dbus types from YAML and convert it to a recursive data
+ structure. Each entry of the original list gets converted into a tuple
+ consisting of the type name and a list with the params for this type,
+ e.g.
+ ['dict', ['string', 'dict', ['string', 'int64']]]
+ is converted to
+ [('dict', [('string', []), ('dict', [('string', []), ('int64', [])]]]
+ """
+ def __preprocess_yaml_type_array(self, typeArray):
+ result = []
+
+ for i in range(len(typeArray)):
+ # Ignore lists because we merge them with the previous element
+ if type(typeArray[i]) is list:
+ continue
+
+ # If there is a next element and it is a list, merge it with the current element.
+ if i < len(typeArray)-1 and type(typeArray[i+1]) is list:
+ result.append((typeArray[i], self.__preprocess_yaml_type_array(typeArray[i+1])))
+ else:
+ result.append((typeArray[i], []))
+
+ return result
""" Take a list of dbus types and perform validity checking, such as:
[ variant [ dict [ int32, int32 ], double ] ]
This function then converts the type-list into a C++ type string.
"""
- def __parse_cpp_type__(self, typeArray):
+ def __parse_cpp_type__(self, typeTuple):
propertyMap = {
'byte': {'cppName': 'uint8_t', 'params': 0},
'boolean': {'cppName': 'bool', 'params': 0},
@@ -92,23 +117,23 @@
'dict': {'cppName': 'std::map', 'params': 2},
'enum': {'cppName': 'enum', 'params': 1, 'noparse': True}}
- first = typeArray.pop(0)
+ if len(typeTuple) != 2:
+ raise RuntimeError("Invalid typeTuple %s" % typeTuple)
+
+ first = typeTuple[0]
entry = propertyMap[first]
result = entry['cppName']
# Handle 0-entry parameter lists.
if (entry['params'] == 0):
- if (len(typeArray) != 0):
- raise RuntimeError("Invalid typeArray %s" % typeArray)
+ if (len(typeTuple[1]) != 0):
+ raise RuntimeError("Invalid typeTuple %s" % typeTuple)
else:
return result
- # Get remainder of the parameter list, which should be the last
- # element.
- rest = typeArray.pop(0)
- if (len(typeArray) != 0):
- raise RuntimeError("Invalid typeArray %s" % typeArray)
+ # Get the parameter list
+ rest = typeTuple[1]
# Confirm parameter count matches.
if (entry['params'] != -1) and (entry['params'] != len(rest)):
@@ -121,7 +146,7 @@
if entry.get('noparse'):
result += ", ".join(rest)
else:
- result += ", ".join(map(lambda e: self.__parse_cpp_type__([e]),
+ result += ", ".join(map(lambda e: self.__parse_cpp_type__(e),
rest))
result += '>'