KPN IoT / senml

Fork of kpn_senml by KPN IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers senml_cbor_parser.h Source File

senml_cbor_parser.h

00001 /*  _  __  ____    _   _ 
00002  * | |/ / |  _ \  | \ | |
00003  * | ' /  | |_) | |  \| |
00004  * | . \  |  __/  | |\  |
00005  * |_|\_\ |_|     |_| \_|
00006  * 
00007  * (c) 2018 KPN
00008  * License: MIT License.
00009  * Author: Jan Bogaerts
00010  * 
00011  * parse cbor header
00012  */
00013 
00014 #ifndef SENMLCBORPARSER
00015 #define SENMLCBORPARSER
00016 
00017 #include <senml_base_parser.h>
00018 #include <senml_enums.h>
00019 #include <senml_logging.h>
00020 #include <senml_helpers.h>
00021 #include <cbor.h>
00022 
00023 enum SenMLCborDataType {};
00024 
00025 #define SENML_CBOR_KEY 1
00026 #define SENML_CBOR_VALUE 2
00027 
00028 
00029 /**
00030  * Inernal helper class for parsing cbor data.
00031  */
00032 class SenMLCborParser: public SenMLBaseParser {
00033 
00034   public:
00035     SenMLCborParser(SenMLPack* root, SenMLStreamMethod format): SenMLBaseParser(root), state(0) 
00036     {
00037         this->ctx.format = format;
00038         this->ctx.baseValue.baseUint = 0;               //init to 0, so we get correct results for first element as well.
00039         this->ctx.baseSum.baseUint = 0;
00040         _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)
00041     };
00042 
00043     //convert the cbor raw data into senml and actuate the records in the root pack.
00044     void parse(Stream* source);
00045 
00046 
00047     void parse(char* source, int length);
00048 
00049 
00050   private:
00051     unsigned char state;                                            //keeps track of the current parse state
00052     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
00053     StreamContext ctx;
00054 
00055     unsigned int parseNext();
00056 
00057     void setValue(void* value, int length, SenMLDataType type);
00058     void setBinaryValue(const char* value, int length);
00059     void processDouble(double value);
00060 
00061     void internalParse();
00062 
00063     unsigned int processBytes(SenMLDataType type);
00064 
00065     unsigned int processArray();
00066 
00067     inline unsigned int processMap()
00068     {
00069         const bool is_indefinite = (peekChar() == (CBOR_MAP | CBOR_VAR_FOLLOWS));
00070         uint64_t map_length = 0;
00071         size_t read_bytes;
00072 
00073         if (is_indefinite){
00074             log_debug("not supported");
00075         }
00076         else 
00077             read_bytes = decode_int(&map_length);
00078 
00079         unsigned char curState = this->state;
00080         size_t i = 0;
00081         while (i < map_length) {
00082             size_t key_read_bytes, value_read_bytes;
00083             this->state = SENML_CBOR_KEY;
00084             key_read_bytes = this->parseNext(); /* key */
00085             this->state = SENML_CBOR_VALUE;
00086             value_read_bytes = this->parseNext(); /* value */
00087             if (key_read_bytes == 0 || value_read_bytes == 0) {
00088                 log_debug("invalid input");
00089                 break;
00090             }
00091             read_bytes += key_read_bytes + value_read_bytes;
00092             ++i;
00093         }
00094         this->state = curState;                                     //reset to the original state. was changed inside loop
00095         this->ctx.baseValue.baseUint = 0;                                        //if there was a base value, reset it for the next run.
00096         return read_bytes;
00097     };
00098 
00099     inline unsigned int processUnsignedInt()
00100     {
00101         uint64_t val; 
00102         size_t read_bytes = cbor_deserialize_uint64_t(&val); 
00103         if(this->state == SENML_CBOR_VALUE){
00104             switch (this->curLabel)
00105             {
00106                 case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseUint = val; break;
00107                 case SENML_CBOR_V_LABEL: 
00108                     uint64_t calculated = this->ctx.baseValue.baseUint + val;
00109                     this->setValue((void*)&calculated, sizeof(uint64_t), CBOR_TYPE_UINT); 
00110                     break;
00111             }
00112         }
00113         else if(this->state == SENML_CBOR_KEY)             //store the value type (basename, baseunit, value, stringvalue,...)
00114             this->curLabel = (int)val;
00115         return read_bytes; 
00116     };
00117 
00118     inline unsigned int processInt()
00119     {
00120         int64_t val; 
00121         size_t read_bytes = cbor_deserialize_int64_t(&val); 
00122         if(this->state == SENML_CBOR_VALUE){
00123             switch (this->curLabel)
00124             {
00125                 case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseInt = val; break;
00126                 case SENML_CBOR_V_LABEL: 
00127                 uint64_t calculated = this->ctx.baseValue.baseInt + val;
00128                     this->setValue((void*)&calculated, sizeof(int64_t), CBOR_TYPE_INT); 
00129                     break;
00130             }
00131         }
00132         else if(this->state == SENML_CBOR_KEY)             //store the value type (basename, baseunit, value, stringvalue,...)
00133             this->curLabel = val;
00134         return read_bytes; 
00135     };
00136 
00137     
00138 };
00139 
00140 #endif // SENMLCBORPARSER
00141 
00142 
00143 
00144 
00145 
00146 
00147