1 /* { dg-do compile } */
2 
3 typedef unsigned _GCC_ATTR_ALIGN_u32t;
4 typedef _GCC_ATTR_ALIGN_u32t _Uint32t __attribute__ ((__aligned__ (4)));
5 typedef unsigned int _GCC_ATTR_ALIGN_u8t __attribute__ ((__mode__ (__QI__)));
6 typedef _GCC_ATTR_ALIGN_u8t _Uint8t __attribute__ ((__aligned__ (1)));
7 typedef unsigned _Sizet;
8 typedef _Sizet size_t;
9 typedef _Uint8t uint8_t;
10 typedef _Uint32t uint32_t;
11 typedef enum
12 {
13   PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_LABEL_OPTIONAL,
14     PROTOBUF_C_LABEL_REPEATED
15 }
16 ProtobufCLabel;
17 typedef enum
18 {
19   PROTOBUF_C_TYPE_INT32, PROTOBUF_C_TYPE_SINT32, PROTOBUF_C_TYPE_SFIXED32,
20     PROTOBUF_C_TYPE_INT64, PROTOBUF_C_TYPE_SINT64, PROTOBUF_C_TYPE_SFIXED64,
21     PROTOBUF_C_TYPE_UINT32, PROTOBUF_C_TYPE_FIXED32, PROTOBUF_C_TYPE_UINT64,
22     PROTOBUF_C_TYPE_FIXED64, PROTOBUF_C_TYPE_FLOAT, PROTOBUF_C_TYPE_DOUBLE,
23     PROTOBUF_C_TYPE_BOOL, PROTOBUF_C_TYPE_ENUM, PROTOBUF_C_TYPE_STRING,
24     PROTOBUF_C_TYPE_BYTES, PROTOBUF_C_TYPE_MESSAGE,
25 }
26 ProtobufCType;
27 typedef struct _ProtobufCBinaryData ProtobufCBinaryData;
28 struct _ProtobufCBinaryData
29 {
30   size_t len;
31 };
32 typedef struct _ProtobufCMessageDescriptor ProtobufCMessageDescriptor;
33 typedef struct _ProtobufCFieldDescriptor ProtobufCFieldDescriptor;
34 typedef struct _ProtobufCMessage ProtobufCMessage;
35 struct _ProtobufCFieldDescriptor
36 {
37   uint32_t id;
38   ProtobufCLabel label;
39   ProtobufCType type;
40   unsigned offset;
41 };
42 struct _ProtobufCMessageDescriptor
43 {
44   unsigned n_fields;
45   const ProtobufCFieldDescriptor *fields;
46 };
47 struct _ProtobufCMessage
48 {
49   const ProtobufCMessageDescriptor *descriptor;
50 };
51 typedef enum
52 {
53   PROTOBUF_C_WIRE_TYPE_VARINT, PROTOBUF_C_WIRE_TYPE_64BIT,
54     PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED, PROTOBUF_C_WIRE_TYPE_START_GROUP,
55     PROTOBUF_C_WIRE_TYPE_END_GROUP, PROTOBUF_C_WIRE_TYPE_32BIT
56 }
57 ProtobufCWireType;
58 size_t tag_pack (uint32_t, uint8_t *);
59 size_t prefixed_message_pack (ProtobufCMessage *, uint8_t *);
60 static inline size_t
uint32_pack(uint32_t value,uint8_t * out)61 uint32_pack (uint32_t value, uint8_t * out)
62 {
63   unsigned rv = 0;
64   if (value >= 0x80)
65     {
66       if (value >= 0x80)
67 	{
68 	  value >>= 7;
69 	}
70     }
71   out[rv++] = value;
72 }
73 
74 static inline size_t
binary_data_pack(const ProtobufCBinaryData * bd,uint8_t * out)75 binary_data_pack (const ProtobufCBinaryData * bd, uint8_t * out)
76 {
77   size_t len = bd->len;
78   size_t rv = uint32_pack (len, out);
79   return rv + len;
80 }
81 
82 static size_t
required_field_pack(const ProtobufCFieldDescriptor * field,const void * member,uint8_t * out)83 required_field_pack (const ProtobufCFieldDescriptor * field,
84 		     const void *member, uint8_t * out)
85 {
86   size_t rv = tag_pack (field->id, out);
87   switch (field->type)
88     {
89     case PROTOBUF_C_TYPE_BYTES:
90       {
91 	const ProtobufCBinaryData *bd =
92 	  ((const ProtobufCBinaryData *) member);
93 	out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
94 	return rv + binary_data_pack (bd, out + rv);
95       }
96     case PROTOBUF_C_TYPE_MESSAGE:
97       {
98 	out[0] |= PROTOBUF_C_WIRE_TYPE_LENGTH_PREFIXED;
99 	return rv +
100 	  prefixed_message_pack (*(ProtobufCMessage * const *) member,
101 				 out + rv);
102       }
103     }
104 }
105 
106 size_t
protobuf_c_message_pack(const ProtobufCMessage * message,uint8_t * out)107 protobuf_c_message_pack (const ProtobufCMessage * message, uint8_t * out)
108 {
109   unsigned i;
110   size_t rv = 0;
111   for (i = 0; i < message->descriptor->n_fields; i++)
112     {
113       const ProtobufCFieldDescriptor *field = message->descriptor->fields + i;
114       const void *member = ((const char *) message) + field->offset;
115       if (field->label == PROTOBUF_C_LABEL_REQUIRED)
116 	rv += required_field_pack (field, member, out + rv);
117     }
118 }
119