Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of kpn_senml by
senml_cbor_parser.cpp
00001 /* _ __ ____ _ _ 00002 * | |/ / | _ \ | \ | | 00003 * | ' / | |_) | | \| | 00004 * | . \ | __/ | |\ | 00005 * |_|\_\ |_| |_| \_| 00006 * 00007 * (c) 2018 KPN 00008 * License: MIT License. 00009 * Author: Jan Bogaerts 00010 * 00011 * parse cbor 00012 */ 00013 00014 00015 #include <senml_cbor_parser.h> 00016 #include <senml_helpers.h> 00017 #include <senml_binary_actuator.h> 00018 00019 void SenMLCborParser::parse(Stream* source) 00020 { 00021 this->ctx.data.stream = source; 00022 this->ctx.dataAsBlob = false; 00023 this->internalParse(); 00024 } 00025 00026 00027 void SenMLCborParser::parse(char* source, int length) 00028 { 00029 this->ctx.data.blob.data = source; 00030 this->ctx.data.blob.curPos = 0; 00031 this->ctx.data.blob.length = length; 00032 this->ctx.dataAsBlob = true; 00033 this->internalParse(); 00034 } 00035 00036 void SenMLCborParser::internalParse() 00037 { 00038 unsigned int read_bytes = this->processArray(); //the root element of senml input is always an array. We do this cause the readable() function on mbed doesn't work as expected, so we can't read until there is no more data, we need to read until we have valid input. 00039 00040 if (read_bytes == 0) { 00041 log_debug("invalid input"); 00042 } 00043 flush(); //make certain that the input streams are empty when done. This also resets any internally stored data. If we don't do this, we can only handle 1 bad input stream, ten it breaks. 00044 } 00045 00046 00047 void SenMLCborParser::processDouble(double value){ 00048 switch (this->curLabel) 00049 { 00050 //case SENML_CBOR_S_LABEL: 00051 case SENML_CBOR_BV_LABEL: this->ctx.baseValue.baseDouble = value; break; 00052 case SENML_CBOR_V_LABEL: 00053 double calculated = this->ctx.baseValue.baseDouble + value; 00054 this->setValue(&calculated, sizeof(double), CBOR_TYPE_DOUBLE); 00055 break; 00056 } 00057 } 00058 00059 unsigned int SenMLCborParser::parseNext() 00060 { 00061 switch (CBOR_TYPE) { 00062 case CBOR_UINT: return this->processUnsignedInt(); 00063 case CBOR_NEGINT: return this->processInt(); 00064 case CBOR_BYTES: return this->processBytes(CBOR_TYPE_DATA); 00065 case CBOR_TEXT: return this->processBytes(CBOR_TYPE_STRING); 00066 case CBOR_ARRAY: return this->processArray(); 00067 case CBOR_MAP: return this->processMap(); 00068 case CBOR_7: { 00069 bool boolRes; 00070 float floatVal; 00071 double doubleVal; 00072 size_t read_bytes; 00073 switch ((int)peekChar()) { 00074 case CBOR_FALSE: 00075 readChar(); //need to remove the char from the stream. 00076 boolRes = false; 00077 this->setValue((void*)&boolRes, sizeof(boolRes), CBOR_TYPE_BOOL); 00078 return 1; 00079 case CBOR_TRUE: 00080 readChar(); //need to remove the char from the stream. 00081 boolRes = true; 00082 this->setValue((void*)&boolRes, sizeof(boolRes), CBOR_TYPE_BOOL); 00083 return 1; 00084 case CBOR_FLOAT16: 00085 read_bytes = cbor_deserialize_float_half(&floatVal); 00086 this->processDouble(floatVal); 00087 return read_bytes; 00088 case CBOR_FLOAT32: 00089 read_bytes = cbor_deserialize_float(&floatVal); 00090 this->processDouble(floatVal); 00091 return read_bytes; 00092 case CBOR_FLOAT64: 00093 read_bytes = cbor_deserialize_double(&doubleVal); 00094 this->processDouble(doubleVal); 00095 return read_bytes; 00096 } 00097 } 00098 } 00099 return 0; //if we get here, something went wrong 00100 } 00101 00102 void SenMLCborParser::setValue(void* value, int length, SenMLDataType type) 00103 { 00104 if(this->curRec){ 00105 this->curRec->actuate(value, length, type); 00106 } 00107 else { 00108 SenMLPack* pack = this->curPack; 00109 if(!pack) 00110 pack = this->root; 00111 if(pack) 00112 pack->actuate(this->curPackName.c_str(), this->curRecName.c_str(), value, length, type); 00113 } 00114 } 00115 00116 void SenMLCborParser::setBinaryValue(const char* value, int length) 00117 { 00118 if(this->curRec){ 00119 ((SenMLBinaryActuator*)this->curRec)->actuate(value, length); 00120 } 00121 else { 00122 SenMLPack* pack = this->curPack; 00123 if(!pack) 00124 pack = this->root; 00125 if(pack) 00126 pack->actuate(this->curPackName.c_str(), this->curRecName.c_str(), value, length, CBOR_TYPE_DATA); 00127 } 00128 } 00129 00130 00131 unsigned int SenMLCborParser::processBytes(SenMLDataType type) 00132 { 00133 uint64_t bytes_length; //needs to be this big for decode_int 00134 size_t bytes_read = decode_int(&bytes_length); 00135 00136 if(bytes_read == 0) return 0; 00137 char buffer[bytes_length + 1]; //need a null 00138 for(int i = 0; i < (int)bytes_length; i++) 00139 buffer[i] = readChar(); 00140 buffer[bytes_length] = 0; //close it, just to be save. not always needed, but it is for strings 00141 00142 if(type == CBOR_TYPE_DATA){ //we are expecting binary data, so it has to be for a binary data value. 00143 if(this->curLabel == SENML_CBOR_VD_LABEL) 00144 this->setBinaryValue(buffer, bytes_length); 00145 else 00146 log_debug("invalid input"); 00147 }else{ //its text 00148 String value; 00149 switch (this->curLabel) 00150 { 00151 case SENML_CBOR_BN_LABEL: 00152 value = buffer; 00153 this->setCurrentPack(value); 00154 break; 00155 case SENML_CBOR_BU_LABEL: 00156 value = buffer; 00157 this->checkBaseUnit(value); 00158 break; 00159 case SENML_CBOR_N_LABEL: 00160 value = buffer; 00161 this->setCurrentRecord(value); 00162 break; 00163 case SENML_CBOR_VS_LABEL: 00164 this->setValue((void*)buffer, bytes_length, CBOR_TYPE_STRING); 00165 break; 00166 } 00167 } 00168 return bytes_read + bytes_length; 00169 } 00170 00171 unsigned int SenMLCborParser::processArray() 00172 { 00173 const bool is_indefinite = (peekChar() == (CBOR_ARRAY | CBOR_VAR_FOLLOWS)); 00174 uint64_t array_length = 0; 00175 size_t read_bytes; 00176 00177 if (is_indefinite){ 00178 log_debug("not supported"); 00179 } 00180 else 00181 read_bytes = decode_int(&array_length); 00182 00183 size_t i = 0; 00184 00185 while (i < array_length) { 00186 size_t inner_read_bytes = this->parseNext(); 00187 if (inner_read_bytes == 0) { 00188 log_debug("invalid input"); 00189 break; 00190 } 00191 read_bytes += inner_read_bytes; 00192 ++i; 00193 } 00194 00195 return read_bytes; 00196 } 00197 00198 00199 00200 00201 00202 00203
Generated on Tue Jul 12 2022 23:07:21 by
1.7.2
