-
Notifications
You must be signed in to change notification settings - Fork 0
/
picopb.cpp
executable file
·119 lines (111 loc) · 2.23 KB
/
picopb.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "picopb.h"
picopb::picopb(uint8_t *buffer,size_t length)
{
this->buffer = buffer;
this->length = length;
this->offset = 0;
this->next_size = 0;
this->next_type = pb_type::INVALID;
}
uint64_t picopb::decode_varint(size_t *size)
{
int index = offset + 1;
uint64_t value = 0;
while(index < length)
{
value<<=7;
value|=(buffer[index]&0x7F);
index++;
if((buffer[index]&0x80)==0)
{
break;
}
}
if(size)
{
*size = index - offset - 1;
}
return value;
}
int picopb::read_varint(uint64_t *out)
{
if(next_type != pb_type::VARINT)
{
return 0;
}
*out = decode_varint(0);
offset += next_size + 1;
next_type = pb_type::INVALID;
return 1;
}
int picopb::read_i64(uint64_t *out)
{
if(next_type != pb_type::I64)
{
return 0;
}
memcpy(out,&buffer[offset+1],8);
offset += 9;
next_type = pb_type::INVALID;
return 1;
}
int picopb::read_string(uint8_t *string,uint8_t bufsz)
{
uint64_t string_len;
size_t varint_len;
if(next_type != pb_type::STRING)
{
return 0;
}
string_len = decode_varint(&varint_len);
if(string_len > bufsz)
{
string_len = bufsz;
}
memcpy(string,&buffer[offset+varint_len+1],string_len);
offset += next_size + 1;
return 0;
}
int picopb::read_i32(uint32_t *out)
{
if(next_type != pb_type::I64)
{
return 0;
}
memcpy(out,&buffer[offset+1],4);
offset += 5;
next_type = pb_type::INVALID;
return 1;
}
pb_type picopb::decode_next(int *id,size_t *size)
{
size_t string_len;
*id = buffer[offset] >> 3;
next_type = (pb_type)(buffer[offset] & 7);
switch(next_type)
{
case pb_type::VARINT:
decode_varint(&next_size);
*size = next_size;
break;
case pb_type::I64:
next_size = 8;
*size = next_size;
break;
case pb_type::STRING:
string_len = decode_varint(&next_size);
next_size += string_len;
*size = string_len;
break;
case pb_type::I32:
next_size = 4;
*size = next_size;
break;
default:
next_type = pb_type::INVALID;
next_size = 0;
*size = next_size;
break;
}
return next_type;
}