File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/libpanda.x/i/panda/varint.h
Criterion Covered Total %
statement 24 24 100.0
branch 7 10 70.0
condition n/a
subroutine n/a
pod n/a
total 31 34 91.1


line stmt bran cond sub pod time code
1             #pragma once
2              
3             #include
4              
5             namespace panda {
6              
7             inline string varint_encode(uint32_t i) {
8             string res;
9             while (i > 127) {
10             res += 0x80 | uint8_t(i & 0x7F);
11             i >>= 7;
12             }
13             res += uint8_t(i);
14             return res;
15             }
16              
17 9           inline uint32_t _varint_decode(const char*& ptr, const char* end) {
18 9           size_t i = 0;
19 9           uint32_t r = 0;
20 18 50         while (ptr != end && (*ptr & 0x80)) {
    100          
21 9           r |= (*ptr & 0x7f) << 7*i;
22 9           ++i;
23 9           ptr++;
24             }
25 9           r |= (*ptr & 0x7f) << 7*i;
26 9           ++ptr;
27 9           return r;
28             }
29              
30             inline uint32_t varint_decode(const string& str, size_t start = 0) {
31             auto begin = str.data() + start;
32             return _varint_decode(begin, str.data() + str.length());
33             }
34              
35             inline string varint_encode_s(int32_t i) {
36             //ZigZag encoding, x86 (both 32,64) only, uses signed bit shift
37             return varint_encode((i << 1) ^ (i >> 31));
38             }
39              
40 9           inline int32_t _varint_decode_s(const char*& ptr, const char* end) {
41             //ZigZag decoding
42 9           uint32_t i = _varint_decode(ptr, end);
43 9           return ((i >> 1) ^ -(i & 1));
44             }
45              
46 9           inline int32_t varint_decode_s(const string& str) {
47 9           auto begin = str.data();
48 9           return _varint_decode_s(begin, str.data() + str.length());
49             }
50              
51             struct VarIntStack {
52             string storage;
53              
54             struct const_iterator {
55             const char* ptr;
56              
57             using size_type = size_t;
58             using value_type = int;
59             using reference = int&;
60             using pointer = int*;
61             using difference_type = std::ptrdiff_t;
62             using iterator_category = std::forward_iterator_tag;
63              
64             int operator*() const {
65             auto copy = ptr; // to prevent ptr from moving
66             return _varint_decode_s(copy, nullptr); // unsafe end
67             }
68              
69             const_iterator& operator++ () {
70             _varint_decode_s(ptr, nullptr);
71             return *this;
72             }
73              
74             const_iterator operator++ (int) {
75             auto res = *this;
76             _varint_decode_s(ptr, nullptr);
77             return res;
78             }
79              
80             bool operator== (const const_iterator& oth) const {return ptr == oth.ptr;}
81             bool operator!= (const const_iterator& oth) const {return !operator ==(oth);}
82             };
83              
84             VarIntStack() = default;
85             VarIntStack(const VarIntStack&) = default;
86             VarIntStack(VarIntStack&&) = default;
87             ~VarIntStack() = default;
88              
89             VarIntStack& operator=(const VarIntStack&) = default;
90             VarIntStack& operator=(VarIntStack&&) = default;
91              
92             void push(int32_t val) {
93             storage.insert(0, varint_encode_s(val));
94             }
95             void pop() {
96             storage.offset(size_of_first());
97             }
98              
99 9           int32_t top() const {
100 9 50         return varint_decode_s(storage.substr(0, size_of_first()));
101             }
102             size_t size() const {
103             size_t res = 0;
104             for (char c : storage) {
105             if (!(c&0x80)) {
106             res += 1;
107             }
108             }
109             return res;
110             }
111              
112             void clear () {
113             storage.clear();
114             }
115              
116             bool empty() const {
117             return storage.empty();
118             }
119              
120             const_iterator begin() const {
121             return const_iterator{storage.data()};
122             }
123              
124             const_iterator end() const {
125             return const_iterator{storage.data() + storage.length()};
126             }
127              
128             private:
129 9           size_t size_of_first() const {
130 9           size_t pos = 0;
131 18 50         for (; pos < storage.size(); ++pos) {
132 18 100         if (!(storage[pos] & 0x80)) {
133 9           break;
134             }
135             }
136 9           return pos + 1;
137             }
138             };
139              
140             }