I think the reason this is getting tricky is because you're trying to
traverse the descriptors first and then look at the message tree afterward.
I would expect it to be much easier if you traverse the message and look at
the descriptors at the same time.

On Tue, Jun 22, 2021 at 10:58 AM J G <progma...@gmail.com> wrote:

> Hi Adam,
>
> That works for the first iteration, but I descend the tree like so:
>
> bool enumpb( const char * pszpath, ENUMPROTOPROC f, const
> google::protobuf::Descriptor * d, uintptr_t param ) {
>
>     std::string path = pszpath;
>
>     for ( int i = 0; i < d->field_count(); i++ ) {
>
>         auto field = d->field( i );
>
>         std::string localpath = pszpath;
>
>         if ( 0 != strcmp( "component", field->name().c_str() ) ) {
>
>             localpath.append( field->name() );
>
>         }
>
>         if ( ( ! localpath.empty() ) && ( '/' != localpath.back() ) ) {
>
>             if ( f && ! f( field, localpath.c_str(), param ) ) {
>
>                 return false;
>
>             }
>
>         }
>
>         auto mt = field->message_type();
>
>         if ( ! mt ) {
>
>             continue;
>
>         } else if ( 0 != strcmp( d->full_name().c_str(),
> mt->full_name().c_str() ) ) {
>
>             std::string localpath2 = localpath;
>
>             if ( ( ! localpath.empty() ) && ( '/' != localpath.back() ) ) {
>
>                 localpath2.append( "/" );
>
>             }
>
>             if ( ! enumpb( hp, report, localpath2.c_str(), f, mt, param )
> ) {
>
>                 return false;
>
>             }
>
>         } else {
>
> //            printf( "Skipping circular %s" EOL, d->full_name().c_str() );
>
>         }
>
>     }
>
>     return true;
>
> }
>
> So I start the traversal like this:
>
> auto d = report->GetDescriptor();
>
> enumpb( "", f, d, param );
>
> And it goes down the variable, visiting each leaf and nested child
> variable, but I can't address each nested child directly that way, can I?
> The mt variable does hold the descriptor for each nested variable at some
> point, but I don't know how I'd derive the variable's instance from it.
>
> On Tuesday, 22 June 2021 at 13:47:15 UTC-4 acoz...@google.com wrote:
>
>> I think the easiest thing would be that wherever you're now storing a
>> google::protobuf::FieldDescriptor*, you can also store a
>> google::protobuf::Message* pointing to the parent message.
>>
>> On Tue, Jun 22, 2021 at 10:41 AM J G <prog...@gmail.com> wrote:
>>
>>> Hi Adam,
>>>
>>> Yes, the HealthReport variable is the parent, and it contains a
>>> HardwareComponent variable, but I am enumerating the from the parent,
>>> meaning I am trying to not hard-code the structure of the contained items.
>>>
>>> So how would I obtain a pointer to the message for each leaf without
>>> hard-coding the member names in there?
>>>
>>> I am able to figure out what value I want to set in each leaf by a map I
>>> have that uses the field's path to match it to the value I want to store.
>>>
>>> On Tuesday, 22 June 2021 at 13:33:11 UTC-4 acoz...@google.com wrote:
>>>
>>>> So is it correct that HealthReport is the top-level message type and
>>>> HardwareComponent is nested somewhere within that? I think what you're
>>>> trying to do is doable, but when you call reflection->SetString(), you have
>>>> to pass the immediate parent message containing the field, not the
>>>> top-level message. You don't need to save the descriptor for each leaf, but
>>>> you do need to save a pointer to the message containing each leaf.
>>>>
>>>> On Tue, Jun 22, 2021 at 10:17 AM J G <prog...@gmail.com> wrote:
>>>>
>>>>> Hi again Adam, and thank you for taking the time to help me.
>>>>>
>>>>> Maybe I haven't explained what I am trying to do properly.
>>>>>
>>>>> I have a protobuf variable, which itself is composed of more nested
>>>>> variables.
>>>>>
>>>>> I am enumerating the fields of the variable.
>>>>>
>>>>> Where the item is a leaf, the field is a simple c-like type (int,
>>>>> bool, string, etc)
>>>>>
>>>>> Where the item itself has fields, it is an agglomerate type and it is
>>>>> descended recursively.
>>>>>
>>>>> My aim is to set each leaf programmatically.
>>>>>
>>>>> So as I traverse the arborescance, I am collecting the field
>>>>> definitions for the leafs.
>>>>>
>>>>> So later, I am addressing the variable again, but trying to set one of
>>>>> its leafs by the field definition I saved. Do I also have to save the
>>>>> descriptor for each leaf?
>>>>>
>>>>> Can what I want to do be done?
>>>>>
>>>>>
>>>>> On Tuesday, 22 June 2021 at 11:52:00 UTC-4 acoz...@google.com wrote:
>>>>>
>>>>>> It looks to me like r->report points to a vafmsg.HealthReport but the
>>>>>> field descriptor refers to a field in another message
>>>>>> (vafmsg.HardwareComponent).
>>>>>>
>>>>>> On Tue, Jun 22, 2021 at 7:42 AM J G <prog...@gmail.com> wrote:
>>>>>>
>>>>>>> Hello Adam,
>>>>>>>
>>>>>>> OK, I understand, so I've tried this, but I get an error.
>>>>>>>
>>>>>>> void my_set_value( class healthreport * r, const char *
>>>>>>> defaultvalue, const google::protobuf::FieldDescriptor * descriptor ) {
>>>>>>>
>>>>>>>     auto reflection = r->report->GetReflection();
>>>>>>>
>>>>>>>     switch( descriptor->type() ) {
>>>>>>>         case google::protobuf::FieldDescriptor::TYPE_STRING: {
>>>>>>>
>>>>>>>                 printf( "REQUESTED TYPE: STRING" EOL );
>>>>>>>                 std::string s = defaultvalue;
>>>>>>>                 reflection->SetString( r->report, descriptor, s );
>>>>>>>
>>>>>>>             }
>>>>>>>             break;
>>>>>>>
>>>>>>>         default:
>>>>>>>
>>>>>>>             printf( "REQUESTED TYPE %d NOT HANDLED" EOL,
>>>>>>> descriptor->type() );
>>>>>>>             break;
>>>>>>>
>>>>>>>     }
>>>>>>>
>>>>>>> }
>>>>>>> Running the above produces the following output:
>>>>>>>
>>>>>>> REQUESTED TYPE: STRING
>>>>>>> [libprotobuf FATAL
>>>>>>> /var/tmp/portage/dev-libs/protobuf-3.15.8/work/protobuf-3.15.8/src/google/protobuf/generated_message_reflection.cc:111]
>>>>>>> Protocol Buffer reflection usage error:
>>>>>>>   Method      : google::protobuf::Reflection::SetString
>>>>>>>   Message type: vafmsg.HealthReport
>>>>>>>   Field       : vafmsg.HardwareComponent.hardware_interface
>>>>>>>   Problem     : Field does not match message type.
>>>>>>> terminate called after throwing an instance of
>>>>>>> 'google::protobuf::FatalException'
>>>>>>>   what():  Protocol Buffer reflection usage error:
>>>>>>>   Method      : google::protobuf::Reflection::SetString
>>>>>>>   Message type: vafmsg.HealthReport
>>>>>>>   Field       : vafmsg.HardwareComponent.hardware_interface
>>>>>>>   Problem     : Field does not match message type.
>>>>>>>
>>>>>>> Here is the proto definition of the variable triggering the
>>>>>>> exception:
>>>>>>>
>>>>>>> message HardwareComponent {
>>>>>>>     optional Component component = 1;
>>>>>>>     repeated DiscreteValue temp = 2;
>>>>>>>     optional string hardware_interface = 3;
>>>>>>>     optional uint32 remaining_life = 4;
>>>>>>>     optional uint32 total_hours = 5;
>>>>>>>     optional EnergyInfo energy = 6;
>>>>>>> }
>>>>>>>
>>>>>>> So the type really IS string, yet an exception is triggered...
>>>>>>>
>>>>>>> What am I doing wrong?
>>>>>>>
>>>>>>> On Friday, 18 June 2021 at 17:56:57 UTC-4 acoz...@google.com wrote:
>>>>>>>
>>>>>>>> Each descriptor describes part of the schema (e.g. a message type,
>>>>>>>> enum type, etc.) but is unrelated to any particular instance of it. As 
>>>>>>>> a
>>>>>>>> result, if you have a descriptor by itself then you can't really modify
>>>>>>>> anything because you separately need an instance of the thing you want 
>>>>>>>> to
>>>>>>>> modify. The way to programmatically modify a message is to use the
>>>>>>>> Reflection
>>>>>>>> <https://github.com/protocolbuffers/protobuf/blob/9d9d8ee18dedfb18371031cd299d1d282ddf707f/src/google/protobuf/message.h#L452>
>>>>>>>> API. You can use Reflection::ListFields() to get a list of all the 
>>>>>>>> fields
>>>>>>>> that are set on the message and then there are Reflection::Get* and
>>>>>>>> Reflection::Set* methods to get and set particular fields.
>>>>>>>>
>>>>>>>> On Fri, Jun 18, 2021 at 9:11 AM J G <prog...@gmail.com> wrote:
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I've got some code that lets me recursively walk a protobuf
>>>>>>>>> variable.
>>>>>>>>>
>>>>>>>>> That part works, I can enumerate the characteristics of a
>>>>>>>>> variable, but the pointers/references returned by the API are const.
>>>>>>>>>
>>>>>>>>> My question is: From a variable's Descriptor or FieldDescriptor,
>>>>>>>>> is it possible to get a non-const pointer/reference to the field to 
>>>>>>>>> be able
>>>>>>>>> to modify it?
>>>>>>>>>
>>>>>>>>> Here's my (simplified) code so far:
>>>>>>>>>
>>>>>>>>> void enumpb(  const google::protobuf::Descriptor * d ) {
>>>>>>>>>
>>>>>>>>>     for ( int i = 0; i < d->field_count(); i++ ) {
>>>>>>>>>
>>>>>>>>>         auto field = d->field( i );
>>>>>>>>>
>>>>>>>>>         // Modify variable code here
>>>>>>>>>         [...]
>>>>>>>>>
>>>>>>>>>         auto mt = field->message_type();
>>>>>>>>>         if ( ! mt ) {
>>>>>>>>>             continue;
>>>>>>>>>         } else if ( 0 != strcmp( d->full_name().c_str(),
>>>>>>>>> mt->full_name().c_str() ) ) {
>>>>>>>>>
>>>>>>>>>             enumpb( mt ) ;
>>>>>>>>>
>>>>>>>>>         }
>>>>>>>>>
>>>>>>>>>     }
>>>>>>>>>
>>>>>>>>>     return true;
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> You received this message because you are subscribed to the Google
>>>>>>>>> Groups "Protocol Buffers" group.
>>>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>>>> send an email to protobuf+u...@googlegroups.com.
>>>>>>>>> To view this discussion on the web visit
>>>>>>>>> https://groups.google.com/d/msgid/protobuf/dcf6bb53-24ce-4404-ab71-0fe3a94adc40n%40googlegroups.com
>>>>>>>>> <https://groups.google.com/d/msgid/protobuf/dcf6bb53-24ce-4404-ab71-0fe3a94adc40n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>>>> .
>>>>>>>>>
>>>>>>>> --
>>>>>>> You received this message because you are subscribed to the Google
>>>>>>> Groups "Protocol Buffers" group.
>>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>>> send an email to protobuf+u...@googlegroups.com.
>>>>>>>
>>>>>> To view this discussion on the web visit
>>>>>>> https://groups.google.com/d/msgid/protobuf/7ef6e77e-8635-4b16-b570-b80f75d207d9n%40googlegroups.com
>>>>>>> <https://groups.google.com/d/msgid/protobuf/7ef6e77e-8635-4b16-b570-b80f75d207d9n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>>> .
>>>>>>>
>>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Protocol Buffers" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to protobuf+u...@googlegroups.com.
>>>>>
>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/protobuf/39fd7a89-426a-453d-9482-4cb3e3658da0n%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/protobuf/39fd7a89-426a-453d-9482-4cb3e3658da0n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Protocol Buffers" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to protobuf+u...@googlegroups.com.
>>>
>> To view this discussion on the web visit
>>> https://groups.google.com/d/msgid/protobuf/764459e6-6f37-42aa-869c-0f8405aa13c6n%40googlegroups.com
>>> <https://groups.google.com/d/msgid/protobuf/764459e6-6f37-42aa-869c-0f8405aa13c6n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Protocol Buffers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to protobuf+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/protobuf/3d9ed924-341b-43cf-8359-c91a93d1916dn%40googlegroups.com
> <https://groups.google.com/d/msgid/protobuf/3d9ed924-341b-43cf-8359-c91a93d1916dn%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to protobuf+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/protobuf/CADqAXr5tTGP-oaGLt8P84m%3Dn%2BwQLGZwJknefh7akQ2f-GjkTmg%40mail.gmail.com.

Reply via email to