From patchwork Wed Aug 10 00:29:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17062 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 64918C3275 for ; Wed, 10 Aug 2022 00:29:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 33B6D63332; Wed, 10 Aug 2022 02:29:23 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1660091363; bh=kSo2TbnvJTbGucRoEEULwHJAUv/a7vzP3VhgcPh9QIM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=v77kDBkCdbR2/cjBtfYeqkOddVrbSOZpE+jgN8qJ1mV+eo4b0hF5eFz9UUvJw+Kr4 oP8J4eYXJzmzktI1yvf42LLjybwvWbijZJEWweXGdYJjbel/L1jIny4dlS0AkSuOhT JHiO0V1Mj5s88qerdoA5xGcUgWivCNBkLh+piRxb25mP18e4Ai1tKrK0vmKqhxEUUl I0UX70R1RMIvbOYifjTMbNYoQOmWstco3oo2oKEzCAm0ws7vvgh4MFT7n/II+F2jYY u1PiivY9PkwCbiLdN1sQZAoS0iRAyf4TsPrChQRC6io5Xe4E+WjyStxe85B8sqCSNO UZoMBkdFEPVsA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 06A5563326 for ; Wed, 10 Aug 2022 02:29:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="a9737xUu"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 931CB481; Wed, 10 Aug 2022 02:29:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1660091359; bh=kSo2TbnvJTbGucRoEEULwHJAUv/a7vzP3VhgcPh9QIM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a9737xUu1a8QYifbPsY5RdhtSqNczAOq3nh9bOCbLNaYLNJnZK8HLeq9eV8rGssLA 0PgFpcNYPW3A2CRbNzrC9NjhVMQf3zp5bfI890nmSkQIuy2BMEBKC6YI+ON0wUskuA n9/ggqLjvnAZCpCdNOQn/+xUNwDO49PvL3K7gERU= To: libcamera-devel@lists.libcamera.org Date: Wed, 10 Aug 2022 03:29:03 +0300 Message-Id: <20220810002906.5406-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220810002906.5406-1-laurent.pinchart@ideasonboard.com> References: <20220810002906.5406-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 1/4] utils: gen-controls: Factor out YAML data handling in classes X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The gen-controls.py script handles the data structure produced by the YAML parser manually through the whole code base. Clean this up by encapsulating it in Control and ControlEnum classes to model a control and its enum values respectively, to decouple YAML data handling from generation. No functional change intended. Signed-off-by: Laurent Pinchart Reviewed-by: Jacopo Mondi --- utils/gen-controls.py | 156 ++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 50 deletions(-) diff --git a/utils/gen-controls.py b/utils/gen-controls.py index 46ba439439ec..f6a3ae39cc84 100755 --- a/utils/gen-controls.py +++ b/utils/gen-controls.py @@ -14,6 +14,90 @@ import sys import yaml +class ControlEnum(object): + def __init__(self, data): + self.__data = data + + @property + def description(self): + """The enum description""" + return self.__data.get('description') + + @property + def name(self): + """The enum name""" + return self.__data.get('name') + + @property + def value(self): + """The enum value""" + return self.__data.get('value') + + +class Control(object): + def __init__(self, name, data): + self.__name = name + self.__data = data + self.__enum = None + + enum_values = data.get('enum') + if enum_values is not None: + self.__enum_values = [ControlEnum(enum) for enum in enum_values] + + @property + def description(self): + """The control description""" + return self.__data.get('description') + + @property + def enum_values(self): + """The enum values, if the control is an enumeration""" + if self.__enum_values is None: + return + for enum in self.__enum_values: + yield enum + + @property + def is_enum(self): + """Is the control an enumeration""" + return self.__data.get('enum') is not None + + @property + def is_draft(self): + """Is the control a draft control""" + return self.__data.get('draft') is not None + + @property + def name(self): + """The control name (CameCase)""" + return self.__name + + @property + def q_name(self): + """The control name, qualified with a namespace""" + ns = 'draft::' if self.is_draft else '' + return ns + self.__name + + @property + def type(self): + typ = self.__data.get('type') + size = self.__data.get('size') + + if typ == 'string': + return 'std::string' + + if size is None: + return typ + + if len(size) > 0: + # fixed-sized Span + span_size = reduce(operator.mul, size) + return f"Span" + else: + # variable-sized Span + return f"Span" + + def snake_case(s): return ''.join([c.isupper() and ('_' + c) or c for c in s]).strip('_') @@ -24,24 +108,6 @@ def format_description(description): return '\n'.join([(line and ' * ' or ' *') + line for line in description]) -def get_ctrl_type(ctrl): - ctrl_type = ctrl['type'] - ctrl_size_arr = ctrl.get('size') - - if ctrl_type == 'string': - return 'std::string' - elif ctrl_size_arr is not None: - if len(ctrl_size_arr) > 0: - # fixed-sized Span - ctrl_span_size = reduce(operator.mul, ctrl_size_arr) - return f"Span" - else: - # variable-sized Span - return f"Span" - else: - return ctrl_type - - def generate_cpp(controls): enum_doc_start_template = string.Template('''/** * \\enum ${name}Enum @@ -67,35 +133,31 @@ ${description} ctrls_map = [] for ctrl in controls: - name, ctrl = ctrl.popitem() - id_name = snake_case(name).upper() - - ctrl_type = get_ctrl_type(ctrl) + id_name = snake_case(ctrl.name).upper() info = { - 'name': name, - 'type': ctrl_type, - 'description': format_description(ctrl['description']), + 'name': ctrl.name, + 'type': ctrl.type, + 'description': format_description(ctrl.description), 'id_name': id_name, } target_doc = ctrls_doc target_def = ctrls_def - if ctrl.get('draft'): + if ctrl.is_draft: target_doc = draft_ctrls_doc target_def = draft_ctrls_def - enum = ctrl.get('enum') - if enum: + if ctrl.is_enum: enum_doc = [] enum_doc.append(enum_doc_start_template.substitute(info)) num_entries = 0 - for entry in enum: + for enum in ctrl.enum_values: value_info = { - 'name': name, - 'value': entry['name'], - 'description': format_description(entry['description']), + 'name': ctrl.name, + 'value': enum.name, + 'description': format_description(enum.description), } enum_doc.append(enum_doc_value_template.substitute(value_info)) num_entries += 1 @@ -110,9 +172,9 @@ ${description} } target_doc.append(enum_values_doc.substitute(values_info)) target_def.append(enum_values_start.substitute(values_info)) - for entry in enum: + for enum in ctrl.enum_values: value_info = { - 'name': entry['name'] + 'name': enum.name } target_def.append(enum_values_values.substitute(value_info)) target_def.append("};") @@ -120,10 +182,7 @@ ${description} target_doc.append(doc_template.substitute(info)) target_def.append(def_template.substitute(info)) - if ctrl.get('draft'): - name = 'draft::' + name - - ctrls_map.append('\t{ ' + id_name + ', &' + name + ' },') + ctrls_map.append('\t{ ' + id_name + ', &' + ctrl.q_name + ' },') return { 'controls_doc': '\n\n'.join(ctrls_doc), @@ -146,31 +205,27 @@ def generate_h(controls): id_value = 1 for ctrl in controls: - name, ctrl = ctrl.popitem() - id_name = snake_case(name).upper() + id_name = snake_case(ctrl.name).upper() ids.append('\t' + id_name + ' = ' + str(id_value) + ',') - ctrl_type = get_ctrl_type(ctrl) - info = { - 'name': name, - 'type': ctrl_type, + 'name': ctrl.name, + 'type': ctrl.type, } target_ctrls = ctrls - if ctrl.get('draft'): + if ctrl.is_draft: target_ctrls = draft_ctrls - enum = ctrl.get('enum') - if enum: + if ctrl.is_enum: target_ctrls.append(enum_template_start.substitute(info)) num_entries = 0 - for entry in enum: + for enum in ctrl.enum_values: value_info = { - 'name': entry['name'], - 'value': entry['value'], + 'name': enum.name, + 'value': enum.value, } target_ctrls.append(enum_value_template.substitute(value_info)) num_entries += 1 @@ -214,6 +269,7 @@ def main(argv): data = open(args.input, 'rb').read() controls = yaml.safe_load(data)['controls'] + controls = [Control(*ctrl.popitem()) for ctrl in controls] if args.template.endswith('.cpp.in'): data = generate_cpp(controls)