Line data Source code
1 : /* Encode a message using callbacks inside oneof fields. 2 : * For encoding, callbacks inside oneofs require nothing special 3 : * so this is just normal callback usage. 4 : */ 5 : 6 : #include <stdio.h> 7 : #include <stdlib.h> 8 : #include <pb_encode.h> 9 : #include "oneof.pb.h" 10 : #include "test_helpers.h" 11 : 12 : /* This is a nanopb-0.4 style global callback, that is referred by function name 13 : * and does not have to be bound separately to the message. It also allows defining 14 : * a custom data type for the field in the structure. 15 : */ 16 2 : bool SubMsg3_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) 17 : { 18 2 : if (ostream && field->tag == SubMsg3_strvalue_tag) 19 : { 20 : /* Our custom data type is char* */ 21 2 : const char *str = *(const char**)field->pData; 22 : 23 2 : if (!pb_encode_tag_for_field(ostream, field)) 24 0 : return false; 25 : 26 2 : return pb_encode_string(ostream, (const uint8_t*)str, strlen(str)); 27 : } 28 : 29 0 : return true; 30 : } 31 : 32 : /* The two callbacks below are traditional callbacks that use function pointers 33 : * defined in pb_callback_t. 34 : */ 35 2 : bool encode_int32_array(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) 36 : { 37 : int i; 38 32 : for (i = 0; i < 15; i++) 39 : { 40 30 : if (!pb_encode_tag_for_field(stream, field)) 41 0 : return false; 42 : 43 30 : if (!pb_encode_varint(stream, i)) 44 0 : return false; 45 : } 46 2 : return true; 47 : } 48 : 49 2 : bool encode_string(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) 50 : { 51 2 : const char *str = "mystring"; 52 : 53 2 : if (!pb_encode_tag_for_field(stream, field)) 54 0 : return false; 55 : 56 2 : return pb_encode_string(stream, (const uint8_t*)str, strlen(str)); 57 : } 58 : 59 6 : int main(int argc, char **argv) 60 : { 61 : uint8_t buffer[256]; 62 6 : OneOfMessage msg = OneOfMessage_init_zero; 63 : pb_ostream_t stream; 64 : int option; 65 : 66 6 : if (argc != 2) 67 : { 68 0 : fprintf(stderr, "Usage: encode_oneof [number]\n"); 69 0 : return 1; 70 : } 71 6 : option = atoi(argv[1]); 72 : 73 : /* Prefix and suffix are used to test that the union does not disturb 74 : * other fields in the same message. */ 75 6 : msg.prefix = 123; 76 : 77 : /* We encode one of the 'values' fields based on command line argument */ 78 6 : if (option == 1) 79 : { 80 1 : msg.which_values = OneOfMessage_intvalue_tag; 81 1 : msg.values.intvalue = 999; 82 : } 83 5 : else if (option == 2) 84 : { 85 1 : msg.which_values = OneOfMessage_strvalue_tag; 86 1 : strcpy(msg.values.strvalue, "abcd"); 87 : } 88 4 : else if (option == 3) 89 : { 90 1 : msg.which_values = OneOfMessage_submsg1_tag; 91 1 : msg.values.submsg1.array.funcs.encode = encode_int32_array; 92 : } 93 3 : else if (option == 4) 94 : { 95 1 : msg.which_values = OneOfMessage_submsg2_tag; 96 1 : msg.values.submsg2.strvalue.funcs.encode = encode_string; 97 : } 98 2 : else if (option == 5) 99 : { 100 1 : msg.which_values = OneOfMessage_submsg3_tag; 101 1 : msg.values.submsg3.which_values = SubMsg3_intvalue_tag; 102 1 : msg.values.submsg3.values.intvalue = 1234; 103 : } 104 1 : else if (option == 6) 105 : { 106 1 : msg.which_values = OneOfMessage_submsg3_tag; 107 1 : msg.values.submsg3.which_values = SubMsg3_strvalue_tag; 108 1 : msg.values.submsg3.values.strvalue = "efgh"; 109 : } 110 : 111 6 : msg.suffix = 321; 112 : 113 6 : stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); 114 : 115 6 : if (pb_encode(&stream, OneOfMessage_fields, &msg)) 116 : { 117 : SET_BINARY_MODE(stdout); 118 6 : fwrite(buffer, 1, stream.bytes_written, stdout); 119 6 : return 0; 120 : } 121 : else 122 : { 123 0 : fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&stream)); 124 0 : return 1; 125 : } 126 : }