lsquic_varint.h revision bc520ef7
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2#ifndef LSQUIC_VARINT_H
3#define LSQUIC_VARINT_H 1
4
5#define VINT_MASK ((1 << 6) - 1)
6
7/* See [draft-ietf-quic-transport-11], section-7.1 */
8#define vint_val2bits(val) (    \
9    ((val) >= (1 << 6)) + ((val) >= (1 << 14)) + ((val) >= (1 << 30)))
10
11#define vint_size(val) (1u << vint_val2bits(val))
12
13#define VINT_MAX_VALUE ((1ull << 62) - 1)
14
15/* Map
16 *  0 -> 6
17 *  1 -> 14
18 *  2 -> 30
19 *  3 -> 62
20 */
21#define vint_bits2shift(bits) ((1 << (3 + (bits))) - 2)
22
23#define VINT_MAX_B(bits_) ((1ull << (vint_bits2shift(bits_))) - 1)
24
25/* Maximum value that can be encoded as one byte: */
26#define VINT_MAX_ONE_BYTE VINT_MAX_B(0)
27
28int
29lsquic_varint_read (const unsigned char *p, const unsigned char *end,
30                                                            uint64_t *valp);
31
32#define vint_read lsquic_varint_read
33
34struct varint_read_state
35{
36    uint64_t    val;
37    int         pos;
38};
39
40int
41lsquic_varint_read_nb (const unsigned char **p, const unsigned char *end,
42                            struct varint_read_state *);
43
44struct varint_read2_state
45{
46    uint64_t                    vr2s_one;
47    struct varint_read_state    vr2s_varint_state;
48#define vr2s_two vr2s_varint_state.val
49    enum {
50        VR2S_READ_ONE_BEGIN = 0,
51        VR2S_READ_ONE_CONTINUE,
52        VR2S_READ_TWO_BEGIN,
53        VR2S_READ_TWO_CONTINUE,
54    }                           vr2s_state;
55};
56
57/* When first called, vr2s_state must be set to 0.
58 *
59 * Returns 0 when both varint values have been read.  They are available
60 * in vr2s_one and vr2s_two.
61 *
62 * Returns -1 when more input is needed.
63 */
64int
65lsquic_varint_read_two (const unsigned char **p, const unsigned char *end,
66                            struct varint_read2_state *);
67
68#if __BYTE_ORDER == __LITTLE_ENDIAN
69#define vint_write(dst, val, bits, len) do {                                \
70    uint64_t buf_ = (val)                                                   \
71                  | (uint64_t) (bits) << vint_bits2shift(bits);             \
72    buf_ = bswap_64(buf_);                                                  \
73    memcpy(dst, (unsigned char *) &buf_ + 8 - (len), (len));                \
74} while (0)
75#else
76#define vint_write(dst, val, bits, len) do {                                \
77    uint64_t buf_ = (val)                                                   \
78                  | (uint64_t) (bits) << vint_bits2shift(bits);             \
79    memcpy(dst, (unsigned char *) &buf_ + 8 - (len), (len));                \
80} while (0)
81#endif
82
83#endif
84