[{"id":13386,"web_url":"https://patchwork.libcamera.org/comment/13386/","msgid":"<20201022024113.GX3942@pendragon.ideasonboard.com>","date":"2020-10-22T02:41:13","subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Wed, Oct 21, 2020 at 04:36:27PM +0200, Jacopo Mondi wrote:\n> For each Control that support enumerated values generate a vector\n> of ControlValues which contains the full list of values.\n> \n> At the expense of a slight increase in memory occupation this change\n> allows the construction of the ControlInfo associated with a Control\n> from the values list, defaulting the minimum and maximum values\n> reported by the ControlInfo.\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  src/libcamera/control_ids.cpp.in |  2 ++\n>  utils/gen-controls.py            | 10 ++++++++++\n>  2 files changed, 12 insertions(+)\n> \n> diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> index 056645cfbdfb..ca0b5b22f899 100644\n> --- a/src/libcamera/control_ids.cpp.in\n> +++ b/src/libcamera/control_ids.cpp.in\n> @@ -6,8 +6,10 @@\n>   *\n>   * This file is auto-generated. Do not edit.\n>   */\n> +#include <vector>\n\nThis should go to control_ids.h.in as that's where you add\nstd::vector<>.\n\n>  #include <libcamera/control_ids.h>\n> +#include <libcamera/controls.h>\n>  \n>  /**\n>   * \\file control_ids.h\n> diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> index bf681503f86a..23aace50f666 100755\n> --- a/utils/gen-controls.py\n> +++ b/utils/gen-controls.py\n> @@ -100,6 +100,8 @@ ${description}\n>  def generate_h(controls):\n>      enum_template_start = string.Template('''enum ${name}Enum {''')\n>      enum_value_template = string.Template('''\\t${name} = ${value},''')\n> +    enum_list_start = string.Template('''static const std::vector<ControlValue> ${name}Values = {''')\n> +    enum_list_values = string.Template('''\\tstatic_cast<int32_t>(${name}),''')\n\nShouldn't you declare the vector as extern const here, and define it in\ncontrol_ids.cpp ? Otherwise you'll duplicate the values in every\ncompilation unit that includes control_ids.h.\n\nI would also make it an std::array, to avoid global objects that have\nnon-trivial constructors. But the ControlValue stored in the vector has\na non-trivial constructor :-/ Do you expect enumerated controls with\nother types than Integer32 ? If not we could make the API more specific,\nbut maybe that's not a very good idea in case we need to extend it\nlater.\n\nstd::array may be best anyway, even with ControlValue, as it will be\nsimpler. Given that we know here how many enumerated values we generate,\nsetting the number of elements in the std::array template parameter\nshouldn't be a problem. Then, you would need to modify the ControlInfo\nconstructor to take a Span<ControlValue> instead of a std::vector<>.\n\n>      template = string.Template('''extern const Control<${type}> ${name};''')\n>  \n>      ctrls = []\n> @@ -140,6 +142,14 @@ def generate_h(controls):\n>                  target_ctrls.append(enum_value_template.substitute(value_info))\n>              target_ctrls.append(\"};\")\n>  \n> +            target_ctrls.append(enum_list_start.substitute(info))\n> +            for entry in enum:\n> +                value_info = {\n> +                    'name': entry['name'],\n> +                }\n> +                target_ctrls.append(enum_list_values.substitute(value_info))\n> +            target_ctrls.append(\"};\")\n> +\n\nNot a candidate for this series, but given that we will soon depend on\njinja at build time (for IPA IPC and for tracing), I think we could\nupgrade the control and property templates to jinja templates, it should\nsimplify this code.\n\n>          target_ctrls.append(template.substitute(info))\n>          id_value += 1\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id EBB10C3D3C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 22 Oct 2020 02:42:00 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6E07361059;\n\tThu, 22 Oct 2020 04:42:00 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D91476034F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 22 Oct 2020 04:41:59 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5A06E53;\n\tThu, 22 Oct 2020 04:41:59 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"AukuBxPQ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1603334519;\n\tbh=ovkFBxgxIzlUq/8lAyq+oOUNeRE25nECQkyEerh7/p8=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=AukuBxPQl7VxF/4NNFBUUZVXX4Y5Lnnp86IRzDGing9u2YvlNCnb/YNgCF03LH5gQ\n\t4gf9NwB63ryheJIOPBSfmG/fZLoA0H5X2l7W9LhYRLvvJ0x+fOpw827542eVL9M4eR\n\tCdTqNUO8AyImq5a3qe3I5Mw9ChoJIBivFwrajfss=","Date":"Thu, 22 Oct 2020 05:41:13 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20201022024113.GX3942@pendragon.ideasonboard.com>","References":"<20201021143635.22846-1-jacopo@jmondi.org>\n\t<20201021143635.22846-7-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20201021143635.22846-7-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":13446,"web_url":"https://patchwork.libcamera.org/comment/13446/","msgid":"<20201023111142.snjd5go3qtcqufr6@uno.localdomain>","date":"2020-10-23T11:11:42","subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Thu, Oct 22, 2020 at 05:41:13AM +0300, Laurent Pinchart wrote:\n> Hi Jacopo,\n>\n> Thank you for the patch.\n>\n> On Wed, Oct 21, 2020 at 04:36:27PM +0200, Jacopo Mondi wrote:\n> > For each Control that support enumerated values generate a vector\n> > of ControlValues which contains the full list of values.\n> >\n> > At the expense of a slight increase in memory occupation this change\n> > allows the construction of the ControlInfo associated with a Control\n> > from the values list, defaulting the minimum and maximum values\n> > reported by the ControlInfo.\n> >\n> > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > ---\n> >  src/libcamera/control_ids.cpp.in |  2 ++\n> >  utils/gen-controls.py            | 10 ++++++++++\n> >  2 files changed, 12 insertions(+)\n> >\n> > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > index 056645cfbdfb..ca0b5b22f899 100644\n> > --- a/src/libcamera/control_ids.cpp.in\n> > +++ b/src/libcamera/control_ids.cpp.in\n> > @@ -6,8 +6,10 @@\n> >   *\n> >   * This file is auto-generated. Do not edit.\n> >   */\n> > +#include <vector>\n>\n> This should go to control_ids.h.in as that's where you add\n> std::vector<>.\n>\n> >  #include <libcamera/control_ids.h>\n> > +#include <libcamera/controls.h>\n> >\n> >  /**\n> >   * \\file control_ids.h\n> > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > index bf681503f86a..23aace50f666 100755\n> > --- a/utils/gen-controls.py\n> > +++ b/utils/gen-controls.py\n> > @@ -100,6 +100,8 @@ ${description}\n> >  def generate_h(controls):\n> >      enum_template_start = string.Template('''enum ${name}Enum {''')\n> >      enum_value_template = string.Template('''\\t${name} = ${value},''')\n> > +    enum_list_start = string.Template('''static const std::vector<ControlValue> ${name}Values = {''')\n> > +    enum_list_values = string.Template('''\\tstatic_cast<int32_t>(${name}),''')\n>\n> Shouldn't you declare the vector as extern const here, and define it in\n> control_ids.cpp ? Otherwise you'll duplicate the values in every\n> compilation unit that includes control_ids.h.\n\nRight right right!\n\nI used a static const as I was wrongly generating the vector\ndefinition in the .h file as extern const, as I got a rightfull linker\nerror for a redefinition.\n\nWhat I do have now looks like (for AeMeteringControl)\n\ncontrol_ids.h:\nenum AeMeteringModeEnum {\n\tMeteringCentreWeighted = 0,\n\tMeteringSpot = 1,\n\tMeteringMatrix = 2,\n\tMeteringCustom = 3,\n};\nextern const std::vector<ControlValue> AeMeteringModeValues;\nextern const Control<int32_t> AeMeteringMode;\n\ncontrol_ids.cpp:\nextern const std::vector<ControlValue> AeMeteringModeValues = {\n\tstatic_cast<int32_t>(MeteringCentreWeighted),\n\tstatic_cast<int32_t>(MeteringSpot),\n\tstatic_cast<int32_t>(MeteringMatrix),\n\tstatic_cast<int32_t>(MeteringCustom),\n};\nextern const Control<int32_t> AeMeteringMode(AE_METERING_MODE, \"AeMeteringMode\");\n\nWhich sounds about right to me.\n\n>\n> I would also make it an std::array, to avoid global objects that have\n> non-trivial constructors. But the ControlValue stored in the vector has\n> a non-trivial constructor :-/ Do you expect enumerated controls with\n> other types than Integer32 ? If not we could make the API more specific,\n> but maybe that's not a very good idea in case we need to extend it\n> later.\n>\n> std::array may be best anyway, even with ControlValue, as it will be\n> simpler. Given that we know here how many enumerated values we generate,\n> setting the number of elements in the std::array template parameter\n> shouldn't be a problem. Then, you would need to modify the ControlInfo\n> constructor to take a Span<ControlValue> instead of a std::vector<>.\n>\n\nI struggled for the last hour to have a construct like this one work\nusing std::array<> and Span<>\n\nUsing std::array<> is fine, I can easily generate that.\nUsing Span<> to transport the array content in the ControlInfo is not\nas passing a new Span<ControlValue> contructed from an array<ControlValue, N>\ncalls the ControlValue contructor\n\n\tControlValue(const T &value)\n\t\t: type_(ControlTypeNone), numElements_(0)\n\t{\n\t\tset(details::control_type<std::remove_cv_t<T>>::value, true,\n\t\t    value.data(), value.size(), sizeof(typename T::value_type));\n\t}\n\nand not the copy constructor. The construction than fails at\n        details::control_type<std::remove_cv_t<T>>::value\n\nAs no specialization is provided for control_type<ControlValue>\n(rightfully.\n\nI got away with:\n        ControlInfo(ControlValue *data, unsigned int size);\nWhich can be easily retrieved from std::array::data() and std::array::size()\n\nIn example (raspberrypi.h)\n\t{\n          &controls::AeMeteringMode,\n          ControlInfo(controls::AeMeteringModeValues.data(),\n          controls::AeMeteringModeValues.size())\n        }\n\nWhich is rather ugly but can be shortened with some macro magic\n\nTo sum up:\n- array: yes\n- Span<ControlValue>: no\n- so using array I access the raw data and transport them to the\n  ControlInfo (copying them in an class member vector at the moment,\n  but it can be improved)\n\nSincerely, I don't see much gain in all this churn compared to using a\nplain std::container but I might be missing something.\n\n\n> >      template = string.Template('''extern const Control<${type}> ${name};''')\n> >\n> >      ctrls = []\n> > @@ -140,6 +142,14 @@ def generate_h(controls):\n> >                  target_ctrls.append(enum_value_template.substitute(value_info))\n> >              target_ctrls.append(\"};\")\n> >\n> > +            target_ctrls.append(enum_list_start.substitute(info))\n> > +            for entry in enum:\n> > +                value_info = {\n> > +                    'name': entry['name'],\n> > +                }\n> > +                target_ctrls.append(enum_list_values.substitute(value_info))\n> > +            target_ctrls.append(\"};\")\n> > +\n>\n> Not a candidate for this series, but given that we will soon depend on\n> jinja at build time (for IPA IPC and for tracing), I think we could\n> upgrade the control and property templates to jinja templates, it should\n> simplify this code.\n>\n> >          target_ctrls.append(template.substitute(info))\n> >          id_value += 1\n> >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 972F8BDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Oct 2020 11:11:46 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3BD2C615D4;\n\tFri, 23 Oct 2020 13:11:46 +0200 (CEST)","from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net\n\t[217.70.183.193])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id B0F8761417\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Oct 2020 13:11:44 +0200 (CEST)","from uno.localdomain (93-34-118-233.ip49.fastwebnet.it\n\t[93.34.118.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 3DBB0240011;\n\tFri, 23 Oct 2020 11:11:43 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Fri, 23 Oct 2020 13:11:42 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20201023111142.snjd5go3qtcqufr6@uno.localdomain>","References":"<20201021143635.22846-1-jacopo@jmondi.org>\n\t<20201021143635.22846-7-jacopo@jmondi.org>\n\t<20201022024113.GX3942@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20201022024113.GX3942@pendragon.ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":13453,"web_url":"https://patchwork.libcamera.org/comment/13453/","msgid":"<20201023202450.GE5979@pendragon.ideasonboard.com>","date":"2020-10-23T20:24:50","subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Fri, Oct 23, 2020 at 01:11:42PM +0200, Jacopo Mondi wrote:\n> On Thu, Oct 22, 2020 at 05:41:13AM +0300, Laurent Pinchart wrote:\n> > On Wed, Oct 21, 2020 at 04:36:27PM +0200, Jacopo Mondi wrote:\n> > > For each Control that support enumerated values generate a vector\n> > > of ControlValues which contains the full list of values.\n> > >\n> > > At the expense of a slight increase in memory occupation this change\n> > > allows the construction of the ControlInfo associated with a Control\n> > > from the values list, defaulting the minimum and maximum values\n> > > reported by the ControlInfo.\n> > >\n> > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > > ---\n> > >  src/libcamera/control_ids.cpp.in |  2 ++\n> > >  utils/gen-controls.py            | 10 ++++++++++\n> > >  2 files changed, 12 insertions(+)\n> > >\n> > > diff --git a/src/libcamera/control_ids.cpp.in b/src/libcamera/control_ids.cpp.in\n> > > index 056645cfbdfb..ca0b5b22f899 100644\n> > > --- a/src/libcamera/control_ids.cpp.in\n> > > +++ b/src/libcamera/control_ids.cpp.in\n> > > @@ -6,8 +6,10 @@\n> > >   *\n> > >   * This file is auto-generated. Do not edit.\n> > >   */\n> > > +#include <vector>\n> >\n> > This should go to control_ids.h.in as that's where you add\n> > std::vector<>.\n> >\n> > >  #include <libcamera/control_ids.h>\n> > > +#include <libcamera/controls.h>\n> > >\n> > >  /**\n> > >   * \\file control_ids.h\n> > > diff --git a/utils/gen-controls.py b/utils/gen-controls.py\n> > > index bf681503f86a..23aace50f666 100755\n> > > --- a/utils/gen-controls.py\n> > > +++ b/utils/gen-controls.py\n> > > @@ -100,6 +100,8 @@ ${description}\n> > >  def generate_h(controls):\n> > >      enum_template_start = string.Template('''enum ${name}Enum {''')\n> > >      enum_value_template = string.Template('''\\t${name} = ${value},''')\n> > > +    enum_list_start = string.Template('''static const std::vector<ControlValue> ${name}Values = {''')\n> > > +    enum_list_values = string.Template('''\\tstatic_cast<int32_t>(${name}),''')\n> >\n> > Shouldn't you declare the vector as extern const here, and define it in\n> > control_ids.cpp ? Otherwise you'll duplicate the values in every\n> > compilation unit that includes control_ids.h.\n> \n> Right right right!\n> \n> I used a static const as I was wrongly generating the vector\n> definition in the .h file as extern const, as I got a rightfull linker\n> error for a redefinition.\n> \n> What I do have now looks like (for AeMeteringControl)\n> \n> control_ids.h:\n> enum AeMeteringModeEnum {\n> \tMeteringCentreWeighted = 0,\n> \tMeteringSpot = 1,\n> \tMeteringMatrix = 2,\n> \tMeteringCustom = 3,\n> };\n> extern const std::vector<ControlValue> AeMeteringModeValues;\n> extern const Control<int32_t> AeMeteringMode;\n> \n> control_ids.cpp:\n> extern const std::vector<ControlValue> AeMeteringModeValues = {\n> \tstatic_cast<int32_t>(MeteringCentreWeighted),\n> \tstatic_cast<int32_t>(MeteringSpot),\n> \tstatic_cast<int32_t>(MeteringMatrix),\n> \tstatic_cast<int32_t>(MeteringCustom),\n> };\n> extern const Control<int32_t> AeMeteringMode(AE_METERING_MODE, \"AeMeteringMode\");\n> \n> Which sounds about right to me.\n\nSeems much more than about right to me :-)\n\n> > I would also make it an std::array, to avoid global objects that have\n> > non-trivial constructors. But the ControlValue stored in the vector has\n> > a non-trivial constructor :-/ Do you expect enumerated controls with\n> > other types than Integer32 ? If not we could make the API more specific,\n> > but maybe that's not a very good idea in case we need to extend it\n> > later.\n> >\n> > std::array may be best anyway, even with ControlValue, as it will be\n> > simpler. Given that we know here how many enumerated values we generate,\n> > setting the number of elements in the std::array template parameter\n> > shouldn't be a problem. Then, you would need to modify the ControlInfo\n> > constructor to take a Span<ControlValue> instead of a std::vector<>.\n> \n> I struggled for the last hour to have a construct like this one work\n> using std::array<> and Span<>\n> \n> Using std::array<> is fine, I can easily generate that.\n> Using Span<> to transport the array content in the ControlInfo is not\n> as passing a new Span<ControlValue> contructed from an array<ControlValue, N>\n> calls the ControlValue contructor\n> \n> \tControlValue(const T &value)\n> \t\t: type_(ControlTypeNone), numElements_(0)\n> \t{\n> \t\tset(details::control_type<std::remove_cv_t<T>>::value, true,\n> \t\t    value.data(), value.size(), sizeof(typename T::value_type));\n> \t}\n> \n> and not the copy constructor. The construction than fails at\n>         details::control_type<std::remove_cv_t<T>>::value\n>\n> As no specialization is provided for control_type<ControlValue>\n> (rightfully.\n\nIf someone wants to introduce this, I think I'll give up on computers\nand go plant tomatoes in a warm country :-)\n\n> I got away with:\n>         ControlInfo(ControlValue *data, unsigned int size);\n> Which can be easily retrieved from std::array::data() and std::array::size()\n> \n> In example (raspberrypi.h)\n> \t{\n>           &controls::AeMeteringMode,\n>           ControlInfo(controls::AeMeteringModeValues.data(),\n>           controls::AeMeteringModeValues.size())\n>         }\n> \n> Which is rather ugly but can be shortened with some macro magic\n> \n> To sum up:\n> - array: yes\n> - Span<ControlValue>: no\n> - so using array I access the raw data and transport them to the\n>   ControlInfo (copying them in an class member vector at the moment,\n>   but it can be improved)\n> \n> Sincerely, I don't see much gain in all this churn compared to using a\n> plain std::container but I might be missing something.\n\nIf it's too much churn then it's probably not worth it indeed. In\ngeneral it's best to avoid non-trivial types for global variables as\nmuch as possible, but not to the extent that would require us to rewrite\nthe C++ standard and implement our own compiler of course :-)\n\n> > >      template = string.Template('''extern const Control<${type}> ${name};''')\n> > >\n> > >      ctrls = []\n> > > @@ -140,6 +142,14 @@ def generate_h(controls):\n> > >                  target_ctrls.append(enum_value_template.substitute(value_info))\n> > >              target_ctrls.append(\"};\")\n> > >\n> > > +            target_ctrls.append(enum_list_start.substitute(info))\n> > > +            for entry in enum:\n> > > +                value_info = {\n> > > +                    'name': entry['name'],\n> > > +                }\n> > > +                target_ctrls.append(enum_list_values.substitute(value_info))\n> > > +            target_ctrls.append(\"};\")\n> > > +\n> >\n> > Not a candidate for this series, but given that we will soon depend on\n> > jinja at build time (for IPA IPC and for tracing), I think we could\n> > upgrade the control and property templates to jinja templates, it should\n> > simplify this code.\n> >\n> > >          target_ctrls.append(template.substitute(info))\n> > >          id_value += 1\n> > >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 23460BDB13\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 23 Oct 2020 20:25:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 9A1FE61B8D;\n\tFri, 23 Oct 2020 22:25:39 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 884A0603C1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 23 Oct 2020 22:25:37 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F0B4AB26;\n\tFri, 23 Oct 2020 22:25:36 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"VO58U5Gq\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1603484737;\n\tbh=1jOCExPOlJX3RgB2Fx/u0wBWVuZWNTh+AT23uWj+EEQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=VO58U5GqwBly8mXRUdSdEU/UciIw1xLdIztyyt1pyEReGxAiLHz4q6U36zj552MOw\n\tCRLeEqklwoo+U6GmNFHdjocMghjWx6rgcMSHaPxZVJ5dZSgcAXfW7GJBMdWMa35FyA\n\tzjRQUPHwlTrDM/e90UD21abhY0e7lTPbkQxD8ONo=","Date":"Fri, 23 Oct 2020 23:24:50 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20201023202450.GE5979@pendragon.ideasonboard.com>","References":"<20201021143635.22846-1-jacopo@jmondi.org>\n\t<20201021143635.22846-7-jacopo@jmondi.org>\n\t<20201022024113.GX3942@pendragon.ideasonboard.com>\n\t<20201023111142.snjd5go3qtcqufr6@uno.localdomain>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20201023111142.snjd5go3qtcqufr6@uno.localdomain>","Subject":"Re: [libcamera-devel] [PATCH v3 06/14] libcamera: controls:\n\tGenerate a vector of enumerated values","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]