This repository has been archived by the owner on Mar 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsenml_cbor_parser.h
146 lines (115 loc) · 4.6 KB
/
senml_cbor_parser.h
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* _ __ ____ _ _
* | |/ / | _ \ | \ | |
* | ' / | |_) | | \| |
* | . \ | __/ | |\ |
* |_|\_\ |_| |_| \_|
*
* (c) 2018 KPN
* License: MIT License.
* Author: Jan Bogaerts
*
* parse cbor header
*/
#ifndef SENMLCBORPARSER
#define SENMLCBORPARSER
#include <senml_base_parser.h>
#include <senml_enums.h>
#include <senml_logging.h>
#include <senml_helpers.h>
#include <cbor.h>
enum SenMLCborDataType {};
#define SENML_CBOR_KEY 1
#define SENML_CBOR_VALUE 2
/**
* Inernal helper class for parsing cbor data.
*/
class SenMLCborParser: public SenMLBaseParser {
public:
SenMLCborParser(SenMLPack* root, SenMLStreamMethod format): SenMLBaseParser(root), state(0)
{
this->ctx.format = format;
this->ctx.baseValue.baseUint = 0; //init to 0, so we get correct results for first element as well.
this->ctx.baseSum.baseUint = 0;
_streamCtx = &this->ctx; //set the global variable so that we don't have to pass it along on the stack all the time (saves mem & codesize)
};
//convert the cbor raw data into senml and actuate the records in the root pack.
void parse(Stream* source);
void parse(char* source, int length);
private:
unsigned char state; //keeps track of the current parse state
int curLabel; //the cbor number that represents the current senml label (unit, value, boolvalue, basename,..). The next item to read has to be the value for the label
StreamContext ctx;
unsigned int parseNext();
void setValue(void* value, int length, SenMLDataType type);
void setBinaryValue(const char* value, int length);
void processDouble(double value);
void internalParse();
unsigned int processBytes(SenMLDataType type);
unsigned int processArray();
inline unsigned int processMap()
{
const bool is_indefinite = (peekChar() == (CBOR_MAP | CBOR_VAR_FOLLOWS));
uint64_t map_length = 0;
size_t read_bytes;
if (is_indefinite){
log_debug("not supported");
}
else
read_bytes = decode_int(&map_length);
unsigned char curState = this->state;
size_t i = 0;
while (i < map_length) {
size_t key_read_bytes, value_read_bytes;
this->state = SENML_CBOR_KEY;
key_read_bytes = this->parseNext(); /* key */
this->state = SENML_CBOR_VALUE;
value_read_bytes = this->parseNext(); /* value */
if (key_read_bytes == 0 || value_read_bytes == 0) {
log_debug("invalid input");
break;
}
read_bytes += key_read_bytes + value_read_bytes;
++i;
}
this->state = curState; //reset to the original state. was changed inside loop
this->ctx.baseValue.baseUint = 0; //if there was a base value, reset it for the next run.
return read_bytes;
};
inline unsigned int processUnsignedInt()
{
uint64_t val;
size_t read_bytes = cbor_deserialize_uint64_t(&val);
if(this->state == SENML_CBOR_VALUE){
switch (this->curLabel)
{
case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseUint = val; break;
case SENML_CBOR_V_LABEL:
uint64_t calculated = this->ctx.baseValue.baseUint + val;
this->setValue((void*)&calculated, sizeof(uint64_t), CBOR_TYPE_UINT);
break;
}
}
else if(this->state == SENML_CBOR_KEY) //store the value type (basename, baseunit, value, stringvalue,...)
this->curLabel = (int)val;
return read_bytes;
};
inline unsigned int processInt()
{
int64_t val;
size_t read_bytes = cbor_deserialize_int64_t(&val);
if(this->state == SENML_CBOR_VALUE){
switch (this->curLabel)
{
case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseInt = val; break;
case SENML_CBOR_V_LABEL:
uint64_t calculated = this->ctx.baseValue.baseInt + val;
this->setValue((void*)&calculated, sizeof(int64_t), CBOR_TYPE_INT);
break;
}
}
else if(this->state == SENML_CBOR_KEY) //store the value type (basename, baseunit, value, stringvalue,...)
this->curLabel = val;
return read_bytes;
};
};
#endif // SENMLCBORPARSER