The BERG Cloud connection library for mbed. This works in conjunction with the BERG Cloud Devshield available via http://bergcloud.com/platform/devkit/
Dependents: LittleCounter-Example
BERGCloudMessageBase.cpp
00001 /* 00002 00003 BERGCloud message pack/unpack 00004 00005 Based on MessagePack http://msgpack.org/ 00006 00007 Copyright (c) 2013 BERG Cloud Ltd. http://bergcloud.com/ 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 00027 */ 00028 00029 #define __STDC_LIMIT_MACROS /* Include C99 stdint defines in C++ code */ 00030 #include <stdint.h> 00031 #include <stddef.h> /* For NULL */ 00032 #include <string.h> /* For memcpy() */ 00033 #include "BERGCloudMessageBase.h" 00034 00035 BERGCloudMessageBase::BERGCloudMessageBase(void) 00036 { 00037 } 00038 00039 BERGCloudMessageBase::~BERGCloudMessageBase(void) 00040 { 00041 } 00042 00043 #define _MP_FIXNUM_POS_MIN 0x00 00044 #define _MP_FIXNUM_POS_MAX 0x7f 00045 #define _MP_FIXMAP_MIN 0x80 00046 #define _MP_FIXMAP_MAX 0x8f 00047 #define _MP_FIXARRAY_MIN 0x90 00048 #define _MP_FIXARRAY_MAX 0x9f 00049 #define _MP_FIXRAW_MIN 0xa0 00050 #define _MP_FIXRAW_MAX 0xbf 00051 #define _MP_NIL 0xc0 00052 #define _MP_BOOL_FALSE 0xc2 00053 #define _MP_BOOL_TRUE 0xc3 00054 #define _MP_FLOAT 0xca 00055 #define _MP_DOUBLE 0xcb 00056 #define _MP_UINT8 0xcc 00057 #define _MP_UINT16 0xcd 00058 #define _MP_UINT32 0xce 00059 #define _MP_UINT64 0xcf 00060 #define _MP_INT8 0xd0 00061 #define _MP_INT16 0xd1 00062 #define _MP_INT32 0xd2 00063 #define _MP_INT64 0xd3 00064 #define _MP_RAW16 0xda 00065 #define _MP_RAW32 0xdb 00066 #define _MP_ARRAY16 0xdc 00067 #define _MP_ARRAY32 0xdd 00068 #define _MP_MAP16 0xde 00069 #define _MP_MAP32 0xdf 00070 #define _MP_FIXNUM_NEG_MIN 0xe0 00071 #define _MP_FIXNUM_NEG_MAX 0xff 00072 00073 #define _MAX_FIXRAW (_MP_FIXRAW_MAX - _MP_FIXRAW_MIN) 00074 #define _MAX_FIXARRAY (_MP_FIXARRAY_MAX - _MP_FIXARRAY_MIN) 00075 #define _MAX_FIXMAP (_MP_FIXMAP_MAX - _MP_FIXMAP_MIN) 00076 00077 uint16_t BERGCloudMessageBase::strlen(const char *string) 00078 { 00079 uint16_t strLen = 0; 00080 00081 /* Find string length */ 00082 if (string != NULL) 00083 { 00084 while ((strLen < UINT16_MAX) && (*string != '\0')) 00085 { 00086 string++; 00087 strLen++; 00088 } 00089 } 00090 00091 return strLen; 00092 } 00093 00094 bool BERGCloudMessageBase::strcompare(const char *s1, const char *s2) 00095 { 00096 uint16_t count = 0; 00097 00098 if ((s1 == NULL) || (s2==NULL)) 00099 { 00100 return false; 00101 } 00102 00103 while ((*s1 != '\0') && (*s2 != '\0')) 00104 { 00105 if (*s1++ != *s2++) 00106 { 00107 return false; 00108 } 00109 00110 if (count++ == UINT16_MAX) 00111 { 00112 return false; 00113 } 00114 } 00115 00116 /* identical */ 00117 return true; 00118 } 00119 00120 00121 /* 00122 Pack methods 00123 */ 00124 00125 bool BERGCloudMessageBase::pack(uint8_t n) 00126 { 00127 if (!available(sizeof(n) + 1)) 00128 { 00129 _LOG_PACK_ERROR_NO_SPACE; 00130 return false; 00131 } 00132 00133 add(_MP_UINT8); 00134 add(n); 00135 return true; 00136 } 00137 00138 bool BERGCloudMessageBase::pack(uint16_t n) 00139 { 00140 if (!available(sizeof(n) + 1)) 00141 { 00142 _LOG_PACK_ERROR_NO_SPACE; 00143 return false; 00144 } 00145 00146 add(_MP_UINT16); 00147 add((uint8_t)(n >> 8)); 00148 add((uint8_t)n); 00149 return true; 00150 } 00151 00152 bool BERGCloudMessageBase::pack(uint32_t n) 00153 { 00154 if (!available(sizeof(n) + 1)) 00155 { 00156 _LOG_PACK_ERROR_NO_SPACE; 00157 return false; 00158 } 00159 00160 add(_MP_UINT32); 00161 add((uint8_t)(n >> 24)); 00162 add((uint8_t)(n >> 16)); 00163 add((uint8_t)(n >> 8)); 00164 add((uint8_t)n); 00165 return true; 00166 } 00167 00168 bool BERGCloudMessageBase::pack(int8_t n) 00169 { 00170 if (!available(sizeof(n) + 1)) 00171 { 00172 _LOG_PACK_ERROR_NO_SPACE; 00173 return false; 00174 } 00175 00176 add(_MP_INT8); 00177 add((uint8_t)n); 00178 return true; 00179 } 00180 00181 bool BERGCloudMessageBase::pack(int16_t n) 00182 { 00183 if (!available(sizeof(n) + 1)) 00184 { 00185 _LOG_PACK_ERROR_NO_SPACE; 00186 return false; 00187 } 00188 00189 add(_MP_INT16); 00190 add((uint8_t)(n >> 8)); 00191 add((uint8_t)n); 00192 return true; 00193 } 00194 00195 bool BERGCloudMessageBase::pack(int32_t n) 00196 { 00197 if (!available(sizeof(n) + 1)) 00198 { 00199 _LOG_PACK_ERROR_NO_SPACE; 00200 return false; 00201 } 00202 00203 add(_MP_INT32); 00204 add((uint8_t)(n >> 24)); 00205 add((uint8_t)(n >> 16)); 00206 add((uint8_t)(n >> 8)); 00207 add((uint8_t)n); 00208 return true; 00209 } 00210 00211 bool BERGCloudMessageBase::pack(float n) 00212 { 00213 uint32_t data; 00214 00215 if (!available(sizeof(n) + 1)) 00216 { 00217 _LOG_PACK_ERROR_NO_SPACE; 00218 return false; 00219 } 00220 00221 /* Convert to data */ 00222 memcpy(&data, &n, sizeof(float)); 00223 00224 add(_MP_FLOAT); 00225 add((uint8_t)(data >> 24)); 00226 add((uint8_t)(data >> 16)); 00227 add((uint8_t)(data >> 8)); 00228 add((uint8_t)data); 00229 return true; 00230 } 00231 00232 bool BERGCloudMessageBase::pack(bool n) 00233 { 00234 /* 00235 Note that Arduino redefines 'true' and 'false' in Arduino.h. 00236 You can undefine them in your code to make them type 'bool' again: 00237 #undef true 00238 #undef false 00239 */ 00240 00241 if (!available(1)) 00242 { 00243 _LOG_PACK_ERROR_NO_SPACE; 00244 return false; 00245 } 00246 00247 add(n ? _MP_BOOL_TRUE : _MP_BOOL_FALSE); 00248 return true; 00249 } 00250 00251 bool BERGCloudMessageBase::pack_nil(void) 00252 { 00253 if (!available(1)) 00254 { 00255 _LOG_PACK_ERROR_NO_SPACE; 00256 return false; 00257 } 00258 00259 add(_MP_NIL); 00260 return true; 00261 } 00262 00263 bool BERGCloudMessageBase::pack_array(uint16_t items) 00264 { 00265 if (items <= _MAX_FIXARRAY) 00266 { 00267 /* Use fix array */ 00268 if (!available(items + 1)) 00269 { 00270 _LOG_PACK_ERROR_NO_SPACE; 00271 return false; 00272 } 00273 00274 add(_MP_FIXARRAY_MIN + items); 00275 } 00276 else 00277 { 00278 /* Use array 16 */ 00279 if (!available(items + 1 + sizeof(uint16_t))) 00280 { 00281 _LOG_PACK_ERROR_NO_SPACE; 00282 return false; 00283 } 00284 00285 add(_MP_ARRAY16); 00286 add((uint8_t)(items >> 8)); 00287 add((uint8_t)items); 00288 } 00289 00290 return true; 00291 } 00292 00293 bool BERGCloudMessageBase::pack_map(uint16_t items) 00294 { 00295 if (items <= _MAX_FIXMAP) 00296 { 00297 /* Use fix map */ 00298 if (!available(items + 1)) 00299 { 00300 _LOG_PACK_ERROR_NO_SPACE; 00301 return false; 00302 } 00303 00304 add(_MP_FIXMAP_MIN + items); 00305 } 00306 else 00307 { 00308 /* Use map 16 */ 00309 if (!available(items + 1 + sizeof(uint16_t))) 00310 { 00311 _LOG_PACK_ERROR_NO_SPACE; 00312 return false; 00313 } 00314 00315 add(_MP_MAP16); 00316 add((uint8_t)(items >> 8)); 00317 add((uint8_t)items); 00318 } 00319 00320 return true; 00321 } 00322 00323 bool BERGCloudMessageBase::pack(uint8_t *data, uint16_t sizeInBytes) 00324 { 00325 /* Pack data */ 00326 if (!pack_raw_header(sizeInBytes)) 00327 { 00328 return false; 00329 } 00330 00331 return pack_raw_data(data, sizeInBytes); 00332 } 00333 00334 bool BERGCloudMessageBase::pack(const char *string) 00335 { 00336 /* Pack a null-terminated C string */ 00337 uint16_t strLen; 00338 00339 strLen = BERGCloudMessageBase::strlen(string); 00340 00341 return pack((uint8_t *)string, strLen); 00342 } 00343 00344 /* Separate header and data methods are provided for raw data*/ 00345 /* so that Arduino strings may be packed without having to create */ 00346 /* a temporary buffer first. */ 00347 00348 bool BERGCloudMessageBase::pack_raw_header(uint16_t sizeInBytes) 00349 { 00350 if (sizeInBytes <= _MAX_FIXRAW) 00351 { 00352 /* Use fix raw */ 00353 if (!available(sizeInBytes + 1)) 00354 { 00355 _LOG_PACK_ERROR_NO_SPACE; 00356 return false; 00357 } 00358 00359 add(_MP_FIXRAW_MIN + sizeInBytes); 00360 } 00361 else 00362 { 00363 /* Use raw 16 */ 00364 if (!available(sizeInBytes + 1 + sizeof(uint16_t))) 00365 { 00366 _LOG_PACK_ERROR_NO_SPACE; 00367 return false; 00368 } 00369 00370 add(_MP_RAW16); 00371 add((uint8_t)(sizeInBytes >> 8)); 00372 add((uint8_t)sizeInBytes); 00373 } 00374 00375 return true; 00376 } 00377 00378 bool BERGCloudMessageBase::pack_raw_data(uint8_t *data, uint16_t sizeInBytes) 00379 { 00380 /* Add data */ 00381 while (sizeInBytes-- > 0) 00382 { 00383 add(*data++); 00384 } 00385 00386 return true; 00387 } 00388 00389 /* 00390 Unpack methods 00391 */ 00392 00393 bool BERGCloudMessageBase::unpack_peek(uint8_t& messagePackType) 00394 { 00395 return peek(&messagePackType); 00396 } 00397 00398 #ifdef BERGCLOUD_LOG 00399 bool BERGCloudMessageBase::unpack_peek(void) 00400 { 00401 uint8_t type; 00402 00403 if (!peek(&type)) 00404 { 00405 return false; 00406 } 00407 00408 if (type <= _MP_FIXNUM_POS_MAX) 00409 { 00410 _LOG("Positive integer\r\n"); 00411 return true; 00412 } 00413 00414 if (IN_RANGE(type, _MP_FIXNUM_NEG_MIN, _MP_FIXNUM_NEG_MAX)) 00415 { 00416 _LOG("Negative integer\r\n"); 00417 return true; 00418 } 00419 00420 if ((type == _MP_MAP16) || (type == _MP_MAP32) || IN_RANGE(type, _MP_FIXMAP_MIN, _MP_FIXMAP_MAX)) 00421 { 00422 _LOG("Map\r\n"); 00423 return true; 00424 } 00425 00426 if ((type == _MP_ARRAY16) || (type == _MP_ARRAY32) || IN_RANGE(type, _MP_FIXARRAY_MIN, _MP_FIXARRAY_MAX)) 00427 { 00428 _LOG("Array\r\n"); 00429 return true; 00430 } 00431 00432 if ((type == _MP_RAW16) || (type == _MP_RAW32) || IN_RANGE(type, _MP_FIXRAW_MIN, _MP_FIXRAW_MAX)) 00433 { 00434 _LOG("Raw\r\n"); 00435 return true; 00436 } 00437 00438 if ((type ==_MP_UINT8) || (type == _MP_UINT16) || (type == _MP_UINT32) || (type == _MP_UINT64)) 00439 { 00440 _LOG("Unsigned integer\r\n"); 00441 return true; 00442 } 00443 00444 if ((type ==_MP_INT8) || (type == _MP_INT16) || (type == _MP_INT32) || (type == _MP_INT64)) 00445 { 00446 _LOG("Signed integer\r\n"); 00447 return true; 00448 } 00449 00450 if (type == _MP_NIL) 00451 { 00452 _LOG("Nil\r\n"); 00453 return true; 00454 } 00455 00456 if (type == _MP_BOOL_FALSE) 00457 { 00458 _LOG("Boolean false\r\n"); 00459 return true; 00460 } 00461 00462 if (type == _MP_BOOL_TRUE) 00463 { 00464 _LOG("Boolean true\r\n"); 00465 return true; 00466 } 00467 00468 if (type == _MP_FLOAT) 00469 { 00470 _LOG("Float\r\n"); 00471 return true; 00472 } 00473 00474 if (type == _MP_DOUBLE) 00475 { 00476 _LOG("Double\r\n"); 00477 return true; 00478 } 00479 00480 _LOG("Unknown\r\n"); 00481 return false; 00482 } 00483 00484 void BERGCloudMessageBase::print(void) 00485 { 00486 uint16_t last_read; 00487 00488 /* Remember the current read position in the raw data */ 00489 last_read = bytesRead; 00490 00491 /* Start reading from the beginning of the data */ 00492 restart(); 00493 00494 /* Print all items */ 00495 while(unpack_peek()) 00496 { 00497 unpack_skip(); 00498 } 00499 00500 /* Return to the last position */ 00501 bytesRead = last_read; 00502 } 00503 00504 void BERGCloudMessageBase::print_bytes(void) 00505 { 00506 uint16_t size = used(); 00507 uint8_t *data = ptr(); 00508 00509 while (size-- > 0) 00510 { 00511 _LOG_HEX(*data); 00512 _LOG(" "); 00513 data++; 00514 } 00515 _LOG("\r\n"); 00516 } 00517 #endif 00518 00519 bool BERGCloudMessageBase::getInteger(void *value, bool valueIsSigned, int32_t min, uint32_t max) 00520 { 00521 uint8_t type; 00522 uint32_t unsignedValue; 00523 int32_t signedValue; 00524 00525 /* Look at next type */ 00526 if (!peek(&type)) 00527 { 00528 _LOG_UNPACK_ERROR_NO_DATA; 00529 return false; 00530 } 00531 00532 /* 00533 * Unsigned types 00534 */ 00535 00536 if (type <= _MP_FIXNUM_POS_MAX) 00537 { 00538 /* Read positive fix num value */ 00539 unsignedValue = read(); 00540 } 00541 else if (type == _MP_UINT8) 00542 { 00543 if (!remaining(sizeof(uint8_t))) 00544 { 00545 _LOG_UNPACK_ERROR_NO_DATA; 00546 return false; 00547 } 00548 00549 /* Read type */ 00550 read(); 00551 00552 /* Read 8-bit unsigned integer */ 00553 unsignedValue = read(); 00554 } 00555 else if (type == _MP_UINT16) 00556 { 00557 if (!remaining(sizeof(uint16_t))) 00558 { 00559 _LOG_UNPACK_ERROR_NO_DATA; 00560 return false; 00561 } 00562 00563 /* Read type */ 00564 read(); 00565 00566 /* Read 16-bit unsigned integer */ 00567 unsignedValue = read(); 00568 unsignedValue <<= 8; 00569 unsignedValue |= read(); 00570 } 00571 else if (type == _MP_UINT32) 00572 { 00573 if (!remaining(sizeof(uint32_t))) 00574 { 00575 _LOG_UNPACK_ERROR_NO_DATA; 00576 return false; 00577 } 00578 00579 /* Read type */ 00580 read(); 00581 00582 /* Read 32-bit unsigned integer */ 00583 unsignedValue = read(); 00584 unsignedValue <<= 8; 00585 unsignedValue |= read(); 00586 unsignedValue <<= 8; 00587 unsignedValue |= read(); 00588 unsignedValue <<= 8; 00589 unsignedValue |= read(); 00590 } 00591 else 00592 { 00593 /* 00594 * Signed values 00595 */ 00596 00597 if (IN_RANGE(type, _MP_FIXNUM_NEG_MIN, _MP_FIXNUM_NEG_MAX)) 00598 { 00599 /* Read negative fix num value */ 00600 uint8_t temp; 00601 temp = read(); 00602 signedValue = (int8_t)temp; /* Convert with sign extension */ 00603 } 00604 else if (type == _MP_INT8) 00605 { 00606 if (!remaining(sizeof(int8_t))) 00607 { 00608 _LOG_UNPACK_ERROR_NO_DATA; 00609 return false; 00610 } 00611 00612 /* Read type */ 00613 read(); 00614 00615 /* Read 8-bit signed integer */ 00616 uint8_t temp; 00617 temp = read(); 00618 signedValue = (int8_t)temp; /* Convert with sign extension */ 00619 } 00620 else if (type == _MP_INT16) 00621 { 00622 if (!remaining(sizeof(int16_t))) 00623 { 00624 _LOG_UNPACK_ERROR_NO_DATA; 00625 return false; 00626 } 00627 00628 /* Read type */ 00629 read(); 00630 00631 /* Read 16-bit signed integer */ 00632 uint16_t temp; 00633 temp = read(); 00634 temp <<= 8; 00635 temp |= read(); 00636 signedValue = (int16_t)temp; /* Convert with sign extension */ 00637 } 00638 else if (type == _MP_INT32) 00639 { 00640 if (!remaining(sizeof(int32_t))) 00641 { 00642 _LOG_UNPACK_ERROR_NO_DATA; 00643 return false; 00644 } 00645 00646 /* Read type */ 00647 read(); 00648 00649 /* Read 32-bit signed integer */ 00650 uint32_t temp; 00651 temp = read(); 00652 temp <<= 8; 00653 temp |= read(); 00654 temp <<= 8; 00655 temp |= read(); 00656 temp <<= 8; 00657 temp |= read(); 00658 signedValue = (int32_t)temp; /* Convert */ 00659 } 00660 else 00661 { 00662 /* Can't convert this type */ 00663 _LOG_UNPACK_ERROR_TYPE; 00664 return false; 00665 } 00666 00667 /* Signed value decoded check range */ 00668 if (signedValue > 0) 00669 { 00670 if ((uint32_t)signedValue > max) 00671 { 00672 _LOG_UNPACK_ERROR_RANGE; 00673 return false; 00674 } 00675 } 00676 else if (signedValue < min) 00677 { 00678 _LOG_UNPACK_ERROR_RANGE; 00679 return false; 00680 } 00681 00682 if (valueIsSigned) 00683 { 00684 *(int32_t *)value = signedValue; 00685 } 00686 else 00687 { 00688 /* Convert to unsigned */ 00689 *(uint32_t *)value = (uint32_t)signedValue; 00690 } 00691 00692 /* Success */ 00693 return true; 00694 } 00695 00696 /* Unsigned value decoded; check range */ 00697 if (unsignedValue > max) 00698 { 00699 _LOG_UNPACK_ERROR_RANGE; 00700 return false; 00701 } 00702 00703 if (valueIsSigned) 00704 { 00705 /* Convert to signed */ 00706 *(int32_t *)value = (int32_t)unsignedValue; 00707 } 00708 else 00709 { 00710 *(uint32_t *)value = unsignedValue; 00711 } 00712 00713 /* Success */ 00714 return true; 00715 } 00716 00717 bool BERGCloudMessageBase::unpack_skip(void) 00718 { 00719 /* Skip next item */ 00720 00721 uint8_t type; 00722 uint32_t bytesToSkip = 0; 00723 00724 /* Must be at least one byte of data */ 00725 if (!remaining(sizeof(uint8_t))) 00726 { 00727 _LOG_UNPACK_ERROR_NO_DATA; 00728 return false; 00729 } 00730 00731 /* Read type */ 00732 type = read(); 00733 00734 if ((type == _MP_UINT8) || (type == _MP_INT8)) 00735 { 00736 bytesToSkip = 1; 00737 } 00738 else if ((type == _MP_UINT16) || (type == _MP_INT16)) 00739 { 00740 bytesToSkip = 2; 00741 } 00742 else if ((type == _MP_UINT32) || (type == _MP_INT32) || (type == _MP_FLOAT)) 00743 { 00744 bytesToSkip = 4; 00745 } 00746 else if ((type == _MP_UINT64) || (type == _MP_INT64) || (type == _MP_DOUBLE)) 00747 { 00748 bytesToSkip = 8; 00749 } 00750 else if ((type == _MP_ARRAY16) || (type == _MP_MAP16)) 00751 { 00752 /* TODO: This could skip all of the array/map elements too. */ 00753 bytesToSkip = 2; 00754 } 00755 else if ((type == _MP_ARRAY32) || (type == _MP_MAP32)) 00756 { 00757 /* TODO: This could skip all of the array/map elements too. */ 00758 bytesToSkip = 4; 00759 } 00760 else if (type == _MP_RAW16) 00761 { 00762 if (!remaining(sizeof(uint16_t))) 00763 { 00764 _LOG_UNPACK_ERROR_NO_DATA; 00765 return false; 00766 } 00767 00768 /* Read 16-bit unsigned integer, data size */ 00769 bytesToSkip = read(); 00770 bytesToSkip = bytesToSkip << 8; 00771 bytesToSkip |= read(); 00772 } 00773 else if (type == _MP_RAW32) 00774 { 00775 if (!remaining(sizeof(uint32_t))) 00776 { 00777 _LOG_UNPACK_ERROR_NO_DATA; 00778 return false; 00779 } 00780 00781 /* read 32-bit unsigned integer, data size */ 00782 bytesToSkip = read(); 00783 bytesToSkip = bytesToSkip << 8; 00784 bytesToSkip |= read(); 00785 bytesToSkip = bytesToSkip << 8; 00786 bytesToSkip |= read(); 00787 bytesToSkip = bytesToSkip << 8; 00788 bytesToSkip |= read(); 00789 } 00790 else if (IN_RANGE(type, _MP_FIXRAW_MIN, _MP_FIXRAW_MAX)) 00791 { 00792 bytesToSkip = type - _MP_FIXRAW_MIN; 00793 } 00794 00795 if (!remaining(bytesToSkip)) 00796 { 00797 _LOG_UNPACK_ERROR_NO_DATA; 00798 return false; 00799 } 00800 00801 while (bytesToSkip-- > 0) 00802 { 00803 /* Discard data */ 00804 read(); 00805 } 00806 00807 /* Success */ 00808 return true; 00809 } 00810 00811 bool BERGCloudMessageBase::unpack(uint8_t& n) 00812 { 00813 uint32_t temp; 00814 00815 if (!getInteger(&temp, false, 0, UINT8_MAX)) 00816 { 00817 return false; 00818 } 00819 00820 n = (uint8_t)temp; 00821 return true; 00822 } 00823 00824 bool BERGCloudMessageBase::unpack(uint16_t& n) 00825 { 00826 uint32_t temp; 00827 00828 if (!getInteger(&temp, false, 0, UINT16_MAX)) 00829 { 00830 return false; 00831 } 00832 00833 n = (uint16_t)temp; 00834 return true; 00835 } 00836 00837 bool BERGCloudMessageBase::unpack(uint32_t& n) 00838 { 00839 uint32_t temp; 00840 00841 if (!getInteger(&temp, false, 0, UINT32_MAX)) 00842 { 00843 return false; 00844 } 00845 00846 n = temp; 00847 return true; 00848 } 00849 00850 bool BERGCloudMessageBase::unpack(int8_t& n) 00851 { 00852 int32_t temp; 00853 00854 if (!getInteger(&temp, true, INT8_MIN, INT8_MAX)) 00855 { 00856 return false; 00857 } 00858 00859 n = (int8_t)temp; 00860 return true; 00861 } 00862 00863 bool BERGCloudMessageBase::unpack(int16_t& n) 00864 { 00865 int32_t temp; 00866 00867 if (!getInteger(&temp, true, INT16_MIN, INT16_MAX)) 00868 { 00869 return false; 00870 } 00871 00872 n = (uint16_t)temp; 00873 return true; 00874 } 00875 00876 bool BERGCloudMessageBase::unpack(int32_t& n) 00877 { 00878 int32_t temp; 00879 00880 if (!getInteger(&temp, true, INT32_MIN, INT32_MAX)) 00881 { 00882 return false; 00883 } 00884 00885 n = temp; 00886 return true; 00887 } 00888 00889 bool BERGCloudMessageBase::unpack(float& n) 00890 { 00891 /* Try to decode the next messagePack item as an 4-byte float */ 00892 uint32_t data; 00893 uint8_t type; 00894 00895 /* Look at next type */ 00896 if (!peek(&type)) 00897 { 00898 _LOG_UNPACK_ERROR_NO_DATA; 00899 return false; 00900 } 00901 00902 if (type == _MP_FLOAT) 00903 { 00904 if (!remaining(sizeof(float))) 00905 { 00906 _LOG_UNPACK_ERROR_NO_DATA; 00907 return false; 00908 } 00909 00910 /* Read type */ 00911 read(); 00912 00913 /* Read 32-bit float */ 00914 data = read(); 00915 data = data << 8; 00916 data |= read(); 00917 data = data << 8; 00918 data |= read(); 00919 data = data << 8; 00920 data |= read(); 00921 00922 /* Convert to float */ 00923 memcpy(&n, &data, sizeof(float)); 00924 00925 /* Success */ 00926 return true; 00927 } 00928 00929 /* Can't convert this type */ 00930 _LOG_UNPACK_ERROR_TYPE; 00931 return false; 00932 } 00933 00934 bool BERGCloudMessageBase::unpack(bool& n) 00935 { 00936 /* Try to decode the next messagePack item as boolean */ 00937 uint8_t type; 00938 00939 /* Look at next type */ 00940 if (!peek(&type)) 00941 { 00942 _LOG_UNPACK_ERROR_NO_DATA; 00943 return false; 00944 } 00945 00946 if ((type == _MP_BOOL_FALSE) || (type == _MP_BOOL_TRUE)) 00947 { 00948 n = (read() == _MP_BOOL_TRUE); 00949 00950 /* Success */ 00951 return true; 00952 } 00953 00954 /* Can't convert this type */ 00955 _LOG_UNPACK_ERROR_TYPE; 00956 return false; 00957 } 00958 00959 bool BERGCloudMessageBase::unpack_nil(void) 00960 { 00961 /* Try to decode the next messagePack item as nil */ 00962 uint8_t type; 00963 00964 /* Look at next type */ 00965 if (!peek(&type)) 00966 { 00967 _LOG_UNPACK_ERROR_NO_DATA; 00968 return false; 00969 } 00970 00971 if (type == _MP_NIL) 00972 { 00973 /* Read type */ 00974 read(); 00975 00976 /* Success */ 00977 return true; 00978 } 00979 00980 /* Can't convert this type */ 00981 _LOG_UNPACK_ERROR_TYPE; 00982 return false; 00983 } 00984 00985 bool BERGCloudMessageBase::unpack_array(uint16_t& items) 00986 { 00987 /* Try to decode the next messagePack item as array */ 00988 uint8_t type; 00989 00990 /* Look at next type */ 00991 if (!peek(&type)) 00992 { 00993 _LOG_UNPACK_ERROR_NO_DATA; 00994 return false; 00995 } 00996 00997 if (IN_RANGE(type, _MP_FIXARRAY_MIN, _MP_FIXARRAY_MAX)) 00998 { 00999 /* Read fix num value */ 01000 items = read() - _MP_FIXARRAY_MIN; 01001 01002 /* Success */ 01003 return true; 01004 } 01005 01006 if (type == _MP_ARRAY16) 01007 { 01008 if (!remaining(sizeof(uint16_t))) 01009 { 01010 _LOG_UNPACK_ERROR_NO_DATA; 01011 return false; 01012 } 01013 01014 /* Read type */ 01015 read(); 01016 01017 /* Read 16-bit unsigned integer */ 01018 items = read(); 01019 items = items << 8; 01020 items |= read(); 01021 01022 /* Success */ 01023 return true; 01024 } 01025 01026 if (type == _MP_ARRAY32) 01027 { 01028 /* Not yet supported */ 01029 _LOG_UNPACK_ERROR_TYPE; 01030 return false; 01031 } 01032 01033 /* Can't convert this type */ 01034 _LOG_UNPACK_ERROR_TYPE; 01035 return false; 01036 } 01037 01038 bool BERGCloudMessageBase::unpack_map(uint16_t& items) 01039 { 01040 /* Try to decode the next messagePack item as array */ 01041 uint8_t type; 01042 01043 /* Look at next type */ 01044 if (!peek(&type)) 01045 { 01046 _LOG_UNPACK_ERROR_NO_DATA; 01047 return false; 01048 } 01049 01050 if (IN_RANGE(type, _MP_FIXMAP_MIN, _MP_FIXMAP_MAX)) 01051 { 01052 /* Read fix num value */ 01053 items = read() - _MP_FIXMAP_MIN; 01054 01055 /* Success */ 01056 return true; 01057 } 01058 01059 if (type == _MP_MAP16) 01060 { 01061 if (!remaining(sizeof(uint16_t))) 01062 { 01063 _LOG_UNPACK_ERROR_NO_DATA; 01064 return false; 01065 } 01066 01067 /* Read type */ 01068 read(); 01069 01070 /* Read 16-bit unsigned integer */ 01071 items = read(); 01072 items = items << 8; 01073 items |= read(); 01074 01075 /* Success */ 01076 return true; 01077 } 01078 01079 if (type == _MP_MAP32) 01080 { 01081 /* Not yet supported */ 01082 _LOG_UNPACK_ERROR_TYPE; 01083 return true; 01084 } 01085 01086 /* Can't convert this type */ 01087 _LOG_UNPACK_ERROR_TYPE; 01088 return false; 01089 } 01090 01091 /* Separate header and data methods are provided for raw data*/ 01092 /* so that Arduino strings may be unpacked without having to create */ 01093 /* a temporary buffer first. */ 01094 01095 bool BERGCloudMessageBase::unpack_raw_header(uint16_t *sizeInBytes) 01096 { 01097 uint8_t type; 01098 01099 /* Look at next type */ 01100 if (!peek(&type)) 01101 { 01102 _LOG_UNPACK_ERROR_NO_DATA; 01103 return false; 01104 } 01105 01106 if (IN_RANGE(type, _MP_FIXRAW_MIN, _MP_FIXRAW_MAX)) 01107 { 01108 /* Read fix raw value */ 01109 *sizeInBytes = read() - _MP_FIXRAW_MIN; 01110 01111 /* Success */ 01112 return true; 01113 } 01114 01115 if (type == _MP_RAW16) 01116 { 01117 if (!remaining(sizeof(uint16_t))) 01118 { 01119 _LOG_UNPACK_ERROR_NO_DATA; 01120 return false; 01121 } 01122 01123 /* Read type */ 01124 read(); 01125 01126 /* Read 16-bit unsigned integer */ 01127 *sizeInBytes = read(); 01128 *sizeInBytes = *sizeInBytes << 8; 01129 *sizeInBytes |= read(); 01130 01131 /* Success */ 01132 return true; 01133 } 01134 01135 if (type == _MP_RAW32) 01136 { 01137 if (!remaining(sizeof(uint32_t))) 01138 { 01139 _LOG_UNPACK_ERROR_NO_DATA; 01140 return false; 01141 } 01142 01143 /* Read type */ 01144 read(); 01145 01146 /* read 32-bit unsigned integer */ 01147 *sizeInBytes = read(); 01148 *sizeInBytes = *sizeInBytes << 8; 01149 *sizeInBytes |= read(); 01150 *sizeInBytes = *sizeInBytes << 8; 01151 *sizeInBytes |= read(); 01152 *sizeInBytes = *sizeInBytes << 8; 01153 *sizeInBytes |= read(); 01154 01155 /* Success */ 01156 return true; 01157 } 01158 01159 /* Can't convert this type */ 01160 _LOG_UNPACK_ERROR_TYPE; 01161 return false; 01162 } 01163 01164 bool BERGCloudMessageBase::unpack_raw_data(uint8_t *pData, uint16_t packedSizeInBytes, uint16_t bufferSizeInBytes) 01165 { 01166 uint8_t data; 01167 01168 /* Unpack all bytes */ 01169 while (packedSizeInBytes-- > 0) 01170 { 01171 data = read(); 01172 01173 /* Only write up to the buffer size */ 01174 if (bufferSizeInBytes-- > 0) 01175 { 01176 *pData++ = data; 01177 } 01178 } 01179 01180 return true; 01181 } 01182 01183 bool BERGCloudMessageBase::unpack(char *pString, uint32_t maxSizeInBytes) 01184 { 01185 /* Try to decode a null-terminated C string */ 01186 uint16_t sizeInBytes; 01187 01188 if (!unpack_raw_header(&sizeInBytes)) 01189 { 01190 return false; 01191 } 01192 01193 if (!remaining(sizeInBytes)) 01194 { 01195 _LOG_UNPACK_ERROR_NO_DATA; 01196 return false; 01197 } 01198 01199 if (!unpack_raw_data((uint8_t *)pString, sizeInBytes, maxSizeInBytes - 1)) /* -1 to allow space for null terminator */ 01200 { 01201 return false; 01202 } 01203 01204 /* Add null terminator */ 01205 pString[sizeInBytes] = '\0'; 01206 01207 /* Success */ 01208 return true; 01209 } 01210 01211 bool BERGCloudMessageBase::unpack(uint8_t *pData, uint32_t maxSizeInBytes, uint32_t *pSizeInBytes) 01212 { 01213 /* Try to decode a block of raw data */ 01214 uint16_t sizeInBytes; 01215 01216 if (!unpack_raw_header(&sizeInBytes)) 01217 { 01218 return false; 01219 } 01220 01221 if (!remaining(sizeInBytes)) 01222 { 01223 _LOG_UNPACK_ERROR_NO_DATA; 01224 return false; 01225 } 01226 01227 if (pSizeInBytes != NULL) 01228 { 01229 *pSizeInBytes = sizeInBytes; 01230 } 01231 01232 return unpack_raw_data(pData, sizeInBytes, maxSizeInBytes); 01233 } 01234 01235 bool BERGCloudMessageBase::unpack_find(const char *key) 01236 { 01237 /* Search for a string key in a map; in this simple */ 01238 /* implementation maps cannot contain maps or arrays */ 01239 uint16_t last_read; 01240 uint16_t map_items; 01241 uint8_t type; 01242 char keyString[MAX_MAP_KEY_STRING_LENGTH+1]; /* +1 for null terminator */ 01243 01244 if (key == NULL) 01245 { 01246 return false; 01247 } 01248 01249 if (strlen(key) > MAX_MAP_KEY_STRING_LENGTH) 01250 { 01251 _LOG("Unpack: Key name too long.\r\n"); 01252 return false; 01253 } 01254 01255 /* Remember the current read position in the raw data */ 01256 last_read = bytesRead; 01257 01258 /* Start reading from the beginning of the data */ 01259 restart(); 01260 01261 while(peek(&type)) 01262 { 01263 if (IN_RANGE(type, _MP_FIXMAP_MIN, _MP_FIXMAP_MAX) || (type == _MP_MAP16)) /* _MP_MAP32 not yet supported */ 01264 { 01265 /* Map found, get number of items */ 01266 unpack_map(map_items); 01267 01268 /* Iterate through the key-value pairs */ 01269 while (map_items-- > 0) 01270 { 01271 if (unpack(keyString, sizeof(keyString))) 01272 { 01273 /* String key found */ 01274 if (strcompare(keyString, key)) 01275 { 01276 /* Match found */ 01277 return true; 01278 } 01279 else 01280 { 01281 /* No match, skip this value */ 01282 unpack_skip(); 01283 } 01284 } 01285 else 01286 { 01287 /* Not a suitable string key; skip this key and value */ 01288 unpack_skip(); 01289 unpack_skip(); 01290 } 01291 } 01292 } 01293 else 01294 { 01295 /* Not a map */ 01296 unpack_skip(); 01297 } 01298 } 01299 01300 /* Not found; return to last position */ 01301 bytesRead = last_read; 01302 return false; 01303 } 01304 01305 bool BERGCloudMessageBase::unpack_find(uint16_t i) 01306 { 01307 /* Search for an index in an array; in this simple */ 01308 /* implementation arrays cannot contain maps or arrays */ 01309 uint16_t last_read; 01310 uint16_t array_items; 01311 uint16_t item; 01312 uint8_t type; 01313 01314 /* Remember the current read position in the raw data */ 01315 last_read = bytesRead; 01316 01317 /* Start reading from the beginning of the data */ 01318 restart(); 01319 01320 while(peek(&type)) 01321 { 01322 if (IN_RANGE(type, _MP_FIXARRAY_MIN, _MP_FIXARRAY_MAX) || (type == _MP_ARRAY16)) /* _MP_ARRAY32 not yet supported */ 01323 { 01324 /* Array found, get number of items */ 01325 unpack_array(array_items); 01326 01327 /* Assume items are numbered starting from one */ 01328 item = 1; 01329 01330 if (i == 0) 01331 { 01332 _LOG("Unpack: Array indexes start from 1.\r\n"); 01333 return false; 01334 } 01335 01336 /* Iterate through the values in the array */ 01337 while (array_items-- > 0) 01338 { 01339 if (item++ == i) 01340 { 01341 /* Found it */ 01342 return true; 01343 } 01344 else 01345 { 01346 /* Skip this item */ 01347 unpack_skip(); 01348 } 01349 } 01350 } 01351 else 01352 { 01353 /* Not an array */ 01354 unpack_skip(); 01355 } 01356 } 01357 01358 /* Not found; return to last position */ 01359 bytesRead = last_read; 01360 return false; 01361 } 01362
Generated on Sun Jul 17 2022 20:45:26 by
1.7.2
BERG Cloud


