blob: d210a725010a9d4710feba73e480948a4870d230 [file] [log] [blame]
Frédéric Lécaille1fceee82019-02-25 15:30:36 +01001/*
2 * include/proto/protocol_buffers.h
3 * This file contains functions and macros declarations for protocol buffers decoding.
4 *
5 * Copyright 2012 Willy Tarreau <w@1wt.eu>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation, version 2.1
10 * exclusively.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef _PROTO_PROTOCOL_BUFFERS_H
23#define _PROTO_PROTOCOL_BUFFERS_H
24
25#include <types/protocol_buffers.h>
26
27#define PBUF_TYPE_VARINT 0
28#define PBUF_TYPE_64BIT 1
29#define PBUF_TYPE_LENGTH_DELIMITED 2
30#define PBUF_TYPE_START_GROUP 3
31#define PBUF_TYPE_STOP_GROUP 4
32#define PBUF_TYPE_32BIT 5
33
34#define PBUF_VARINT_DONT_STOP_BIT 7
35#define PBUF_VARINT_DONT_STOP_BITMASK (1 << PBUF_VARINT_DONT_STOP_BIT)
36#define PBUF_VARINT_DATA_BITMASK ~PBUF_VARINT_DONT_STOP_BITMASK
37
38/*
39 * Decode a protocol buffers varint located in a buffer at <pos> address with
40 * <len> as length. The decoded value is stored at <val>.
41 * Returns 1 if succeeded, 0 if not.
42 */
43static inline int
44protobuf_varint(uint64_t *val, unsigned char *pos, size_t len)
45{
46 unsigned int shift;
47
48 *val = 0;
49 shift = 0;
50
51 while (len > 0) {
52 int stop = !(*pos & PBUF_VARINT_DONT_STOP_BITMASK);
53
54 *val |= ((uint64_t)(*pos & PBUF_VARINT_DATA_BITMASK)) << shift;
55
56 ++pos;
57 --len;
58
59 if (stop)
60 break;
61 else if (!len)
62 return 0;
63
64 shift += 7;
65 /* The maximum length in bytes of a 64-bit encoded value is 10. */
66 if (shift > 70)
67 return 0;
68 }
69
70 return 1;
71}
72
73/*
74 * Decode a protocol buffers varint located in a buffer at <pos> offset address with
75 * <len> as length address. Update <pos> and <len> consequently. Decrease <*len>
76 * by the number of decoded bytes. The decoded value is stored at <val>.
77 * Returns 1 if succeeded, 0 if not.
78 */
79static inline int
80protobuf_decode_varint(uint64_t *val, unsigned char **pos, size_t *len)
81{
82 unsigned int shift;
83
84 *val = 0;
85 shift = 0;
86
87 while (*len > 0) {
88 int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
89
90 *val |= ((uint64_t)**pos & PBUF_VARINT_DATA_BITMASK) << shift;
91
92 ++*pos;
93 --*len;
94
95 if (stop)
96 break;
97 else if (!*len)
98 return 0;
99
100 shift += 7;
101 /* The maximum length in bytes of a 64-bit encoded value is 10. */
102 if (shift > 70)
103 return 0;
104 }
105
106 return 1;
107}
108
109/*
110 * Skip a protocol buffer varint found at <pos> as position address with <len>
111 * as available length address. Update <*pos> to make it point to the next
112 * available byte. Decrease <*len> by the number of skipped bytes.
113 * Returns 1 if succeeded, 0 if not.
114 */
115static inline int
116protobuf_skip_varint(unsigned char **pos, size_t *len)
117{
118 unsigned int shift;
119
120 shift = 0;
121
122 while (*len > 0) {
123 int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
124
125 ++*pos;
126 --*len;
127
128 if (stop)
129 break;
130 else if (!*len)
131 return 0;
132
133 shift += 7;
134 /* The maximum length in bytes of a 64-bit encoded value is 10. */
135 if (shift > 70)
136 return 0;
137 }
138
139 return 1;
140}
141
142/*
143 * If succeeded, return the length of a prococol buffers varint found at <pos> as
144 * position address, with <len> as address of the available bytes at <*pos>.
145 * Update <*pos> to make it point to the next available byte. Decrease <*len>
146 * by the number of bytes used to encode this varint.
147 * Return -1 if failed.
148 */
149static inline int
150protobuf_varint_getlen(unsigned char **pos, size_t *len)
151{
152 unsigned char *spos;
153 unsigned int shift;
154
155 shift = 0;
156 spos = *pos;
157
158 while (*len > 0) {
159 int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
160
161 ++*pos;
162 --*len;
163
164 if (stop)
165 break;
166 else if (!*len)
167 return -1;
168
169 shift += 7;
170 /* The maximum length in bytes of a 64-bit encoded value is 10. */
171 if (shift > 70)
172 return -1;
173 }
174
175 return *pos - spos;
176}
177
178#endif /* _PROTO_PROTOCOL_BUFFERS_H */
179
180/*
181 * Local variables:
182 * c-indent-level: 8
183 * c-basic-offset: 8
184 * End:
185 */