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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BERGCloudMessageBase.cpp Source File

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