lsquic_varint.h revision 7d09751d
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