From patchwork Thu Oct 6 23:07:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17556 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 3B182BD16B for ; Thu, 6 Oct 2022 23:07:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F232862D08; Fri, 7 Oct 2022 01:07:56 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1665097677; bh=q6SCLqt0jmn10adSE30c75HoqERoAggP/7dZnuz2fCo=; 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=d4e9dZLt9C7TjmxycuP2AmqUQqvJtPcWbrb7uc7kSW2nlCD+duV6NV0jqY95s9Ip0 9s/hgE43wEBuo06Bc2mPbRhPuGhGsXd6avbdl8CE+tJ8U1IbOxQ6lIlA1yjzpHCtSN HR3f9yyUylR6rBs+ENf6E2w+g+x3A69ITUlr1l+Cid9VywnN2cTlfpNByxl4jkQohH ci99pFb0S0DhquK/zVs62QvTB5cg4KA0j47CerLPDd1oYOWuiQ5UWAZThLlzeyZAfz xRYOKCfO3YQ9qjQRULAipJ1A4bCJmR28IO+Ia45mes7hN5HyYQMdftVksZOdnAQrC/ +t7nAK4zVp5qg== 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 4314B603D7 for ; Fri, 7 Oct 2022 01:07:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="MdVzHwP/"; 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 BE7A86D6; Fri, 7 Oct 2022 01:07:54 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1665097675; bh=q6SCLqt0jmn10adSE30c75HoqERoAggP/7dZnuz2fCo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MdVzHwP/mEP0pWJNwHTbuOQbSqfXGvj+Y7m5HoBBhhDt0gCG0A/Wn6OVEozOCEOj7 p9vgNYQYlWg6r/r0EU8LHT7dfy4Q8HabpdFGKuXKaZgZXhFUxbVuyhShvE4Z3+f457 vBNcFMAINaaXGZfhi6Cl+bScWGCxsJc2KlL8OAgc= To: libcamera-devel@lists.libcamera.org Date: Fri, 7 Oct 2022 02:07:44 +0300 Message-Id: <20221006230747.11688-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20221006230747.11688-1-laurent.pinchart@ideasonboard.com> References: <20221006230747.11688-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 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 Reviewed-by: Umang Jain --- Changes since v1: - Use self.__enum_values to check if Control is an enum - Fix typos --- 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..d6b4e30001b2 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_values = 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.__enum_values 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 (CamelCase)""" + 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)