terence zhang / wakaama
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers utils.c Source File

utils.c

00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2013, 2014 Intel Corporation and others.
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * The Eclipse Distribution License is available at
00011  *    http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    David Navarro, Intel Corporation - initial API and implementation
00015  *    Toby Jaffey - Please refer to git log
00016  *    
00017  *******************************************************************************/
00018 
00019 /*
00020  Copyright (c) 2013, 2014 Intel Corporation
00021 
00022  Redistribution and use in source and binary forms, with or without modification,
00023  are permitted provided that the following conditions are met:
00024 
00025      * Redistributions of source code must retain the above copyright notice,
00026        this list of conditions and the following disclaimer.
00027      * Redistributions in binary form must reproduce the above copyright notice,
00028        this list of conditions and the following disclaimer in the documentation
00029        and/or other materials provided with the distribution.
00030      * Neither the name of Intel Corporation nor the names of its contributors
00031        may be used to endorse or promote products derived from this software
00032        without specific prior written permission.
00033 
00034  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00035  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00036  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00037  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00038  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00039  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00040  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00041  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00042  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00043  THE POSSIBILITY OF SUCH DAMAGE.
00044 
00045  David Navarro <david.navarro@intel.com>
00046 
00047 */
00048 
00049 #include "internals.h"
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include <stdio.h>
00053 #include <float.h>
00054 
00055 
00056 int utils_plainTextToInt64(uint8_t * buffer,
00057                            int length,
00058                            int64_t * dataP)
00059 {
00060     uint64_t result = 0;
00061     int sign = 1;
00062     int i = 0;
00063 
00064     if (0 == length) return 0;
00065 
00066     if (buffer[0] == '-')
00067     {
00068         sign = -1;
00069         i = 1;
00070     }
00071 
00072     while (i < length)
00073     {
00074         if ('0' <= buffer[i] && buffer[i] <= '9')
00075         {
00076             if (result > (UINT64_MAX / 10)) return 0;
00077             result *= 10;
00078             result += buffer[i] - '0';
00079         }
00080         else
00081         {
00082             return 0;
00083         }
00084         i++;
00085     }
00086 
00087     if (result > INT64_MAX) return 0;
00088 
00089     if (sign == -1)
00090     {
00091         *dataP = 0 - result;
00092     }
00093     else
00094     {
00095         *dataP = result;
00096     }
00097 
00098     return 1;
00099 }
00100 
00101 int utils_plainTextToFloat64(uint8_t * buffer,
00102                              int length,
00103                              double * dataP)
00104 {
00105     double result;
00106     int sign;
00107     int i;
00108 
00109     if (0 == length) return 0;
00110 
00111     if (buffer[0] == '-')
00112     {
00113         sign = -1;
00114         i = 1;
00115     }
00116     else
00117     {
00118         sign = 1;
00119         i = 0;
00120     }
00121 
00122     result = 0;
00123     while (i < length && buffer[i] != '.')
00124     {
00125         if ('0' <= buffer[i] && buffer[i] <= '9')
00126         {
00127             if (result > (DBL_MAX / 10)) return 0;
00128             result *= 10;
00129             result += (buffer[i] - '0');
00130         }
00131         else
00132         {
00133             return 0;
00134         }
00135         i++;
00136     }
00137     if (buffer[i] == '.')
00138     {
00139         double dec;
00140 
00141         i++;
00142         if (i == length) return 0;
00143 
00144         dec = 0.1;
00145         while (i < length)
00146         {
00147             if ('0' <= buffer[i] && buffer[i] <= '9')
00148             {
00149                 if (result > (DBL_MAX - 1)) return 0;
00150                 result += (buffer[i] - '0') * dec;
00151                 dec /= 10;
00152             }
00153             else
00154             {
00155                 return 0;
00156             }
00157             i++;
00158         }
00159     }
00160 
00161     *dataP = result * sign;
00162     return 1;
00163 }
00164 
00165 size_t utils_intToText(int64_t data,
00166                        uint8_t * string,
00167                        size_t length)
00168 {
00169     int index;
00170     bool minus;
00171     size_t result;
00172 
00173     if (data < 0)
00174     {
00175         minus = true;
00176         data = 0 - data;
00177     }
00178     else
00179     {
00180         minus = false;
00181     }
00182 
00183     index = length - 1;
00184     do
00185     {
00186         string[index] = '0' + data%10;
00187         data /= 10;
00188         index --;
00189     } while (index >= 0 && data > 0);
00190 
00191     if (data > 0) return 0;
00192 
00193     if (minus == true)
00194     {
00195         if (index == 0) return 0;
00196         string[index] = '-';
00197     }
00198     else
00199     {
00200         index++;
00201     }
00202 
00203     result = length - index;
00204 
00205     if (result < length)
00206     {
00207         memmove(string, string + index, result);
00208     }
00209 
00210     return result;
00211 }
00212 
00213 size_t utils_floatToText(double data,
00214                          uint8_t * string,
00215                          size_t length)
00216 {
00217     size_t intLength;
00218     size_t decLength;
00219     int64_t intPart;
00220     double decPart;
00221 
00222     if (data <= (double)INT64_MIN || data >= (double)INT64_MAX) return 0;
00223 
00224     intPart = (int64_t)data;
00225     decPart = data - intPart;
00226     if (decPart < 0)
00227     {
00228         decPart = 1 - decPart;
00229     }
00230     else
00231     {
00232         decPart = 1 + decPart;
00233     }
00234 
00235     if (decPart <= 1 + FLT_EPSILON)
00236     {
00237         decPart = 0;
00238     }
00239 
00240     if (intPart == 0 && data < 0)
00241     {
00242         // deal with numbers between -1 and 0
00243         if (length < 4) return 0;   // "-0.n"
00244         string[0] = '-';
00245         string[1] = '0';
00246         intLength = 2;
00247     }
00248     else
00249     {
00250         intLength = utils_intToText(intPart, string, length);
00251         if (intLength == 0) return 0;
00252     }
00253     decLength = 0;
00254     if (decPart >= FLT_EPSILON)
00255     {
00256         double noiseFloor;
00257 
00258         if (intLength >= length - 1) return 0;
00259 
00260         noiseFloor = FLT_EPSILON;
00261         do
00262         {
00263             decPart *= 10;
00264             noiseFloor *= 10;
00265         } while (decPart - (int64_t)decPart > noiseFloor);
00266 
00267         decLength = utils_intToText(decPart, string + intLength, length - intLength);
00268         if (decLength <= 1) return 0;
00269 
00270         // replace the leading 1 with a dot
00271         string[intLength] = '.';
00272     }
00273 
00274     return intLength + decLength;
00275 }
00276 
00277 size_t utils_int64ToPlainText(int64_t data,
00278                               uint8_t ** bufferP)
00279 {
00280 #define _PRV_STR_LENGTH 32
00281     uint8_t string[_PRV_STR_LENGTH];
00282     size_t length;
00283 
00284     length = utils_intToText(data, string, _PRV_STR_LENGTH);
00285     if (length == 0) return 0;
00286 
00287     *bufferP = (uint8_t *)lwm2m_malloc(length);
00288     if (NULL == *bufferP) return 0;
00289 
00290     memcpy(*bufferP, string, length);
00291 
00292     return length;
00293 }
00294 
00295 
00296 size_t utils_float64ToPlainText(double data,
00297                                 uint8_t ** bufferP)
00298 {
00299     uint8_t string[_PRV_STR_LENGTH * 2];
00300     size_t length;
00301 
00302     length = utils_floatToText(data, string, _PRV_STR_LENGTH * 2);
00303     if (length == 0) return 0;
00304 
00305     *bufferP = (uint8_t *)lwm2m_malloc(length);
00306     if (NULL == *bufferP) return 0;
00307 
00308     memcpy(*bufferP, string, length);
00309 
00310     return length;
00311 }
00312 
00313 
00314 size_t utils_boolToPlainText(bool data,
00315                              uint8_t ** bufferP)
00316 {
00317     return utils_int64ToPlainText((int64_t)(data?1:0), bufferP);
00318 }
00319 
00320 lwm2m_binding_t utils_stringToBinding(uint8_t * buffer,
00321                                       size_t length)
00322 {
00323     if (length == 0) return BINDING_UNKNOWN;
00324 
00325     switch (buffer[0])
00326     {
00327     case 'U':
00328         switch (length)
00329         {
00330         case 1:
00331             return BINDING_U;
00332         case 2:
00333             switch (buffer[1])
00334             {
00335             case 'Q':
00336                  return BINDING_UQ;
00337             case 'S':
00338                  return BINDING_US;
00339             default:
00340                 break;
00341             }
00342             break;
00343         case 3:
00344             if (buffer[1] == 'Q' && buffer[2] == 'S')
00345             {
00346                 return BINDING_UQS;
00347             }
00348             break;
00349         default:
00350             break;
00351         }
00352         break;
00353 
00354         case 'S':
00355             switch (length)
00356             {
00357             case 1:
00358                 return BINDING_S;
00359             case 2:
00360                 if (buffer[1] == 'Q')
00361                 {
00362                     return BINDING_SQ;
00363                 }
00364                 break;
00365             default:
00366                 break;
00367             }
00368             break;
00369 
00370         default:
00371             break;
00372     }
00373 
00374     return BINDING_UNKNOWN;
00375 }
00376 
00377 lwm2m_media_type_t utils_convertMediaType(coap_content_type_t type)
00378 {
00379     // Here we just check the content type is a valid value for LWM2M
00380     switch((uint16_t)type)
00381     {
00382     case TEXT_PLAIN:
00383         return LWM2M_CONTENT_TEXT;
00384     case APPLICATION_OCTET_STREAM:
00385         return LWM2M_CONTENT_OPAQUE;
00386     case LWM2M_CONTENT_TLV_OLD:
00387         return LWM2M_CONTENT_TLV_OLD;
00388     case LWM2M_CONTENT_TLV:
00389         return LWM2M_CONTENT_TLV;
00390     case LWM2M_CONTENT_JSON_OLD:
00391         return LWM2M_CONTENT_JSON_OLD;
00392     case LWM2M_CONTENT_JSON:
00393         return LWM2M_CONTENT_JSON;
00394     case APPLICATION_LINK_FORMAT:
00395         return LWM2M_CONTENT_LINK;
00396 
00397     default:
00398         return LWM2M_CONTENT_TEXT;
00399     }
00400 }
00401 
00402 #ifdef LWM2M_CLIENT_MODE
00403 lwm2m_server_t * utils_findServer(lwm2m_context_t * contextP,
00404                                   void * fromSessionH)
00405 {
00406     lwm2m_server_t * targetP;
00407 
00408     targetP = contextP->serverList;
00409     while (targetP != NULL
00410         && false == lwm2m_session_is_equal(targetP->sessionH, fromSessionH, contextP->userData))
00411     {
00412         targetP = targetP->next;
00413     }
00414 
00415     return targetP;
00416 }
00417 #endif
00418 
00419 lwm2m_server_t * utils_findBootstrapServer(lwm2m_context_t * contextP,
00420                                            void * fromSessionH)
00421 {
00422 #ifdef LWM2M_CLIENT_MODE
00423 
00424     lwm2m_server_t * targetP;
00425 
00426     targetP = contextP->bootstrapServerList;
00427     while (targetP != NULL
00428         && false == lwm2m_session_is_equal(targetP->sessionH, fromSessionH, contextP->userData))
00429     {
00430         targetP = targetP->next;
00431     }
00432 
00433     return targetP;
00434 
00435 #else
00436 
00437     return NULL;
00438 
00439 #endif
00440 }
00441 
00442 int utils_isAltPathValid(const char * altPath)
00443 {
00444     int i;
00445 
00446     if (altPath == NULL) return 0;
00447 
00448     if (altPath[0] != '/') return 0;
00449 
00450     for (i = 1 ; altPath[i] != 0 ; i++)
00451     {
00452         // TODO: Support multi-segment alternative path
00453         if (altPath[i] == '/') return 0;
00454         // TODO: Check needs for sub-delims, ':' and '@'
00455         if ((altPath[i] < 'A' || altPath[i] > 'Z')      // ALPHA
00456          && (altPath[i] < 'a' || altPath[i] > 'z')
00457          && (altPath[i] < '0' || altPath[i] > '9')      // DIGIT
00458          && (altPath[i] != '-')                         // Other unreserved
00459          && (altPath[i] != '.')
00460          && (altPath[i] != '_')
00461          && (altPath[i] != '~')
00462          && (altPath[i] != '%'))                        // pct_encoded
00463         {
00464             return 0;
00465         }
00466 
00467     }
00468     return 1;
00469 }
00470 
00471 // copy a string in a buffer.
00472 // return the number of copied bytes or -1 if the buffer is not large enough
00473 int utils_stringCopy(char * buffer,
00474                      size_t length,
00475                      const char * str)
00476 {
00477     size_t i;
00478 
00479     for (i = 0 ; i < length && str[i] != 0 ; i++)
00480     {
00481         buffer[i] = str[i];
00482     }
00483 
00484     if (i == length) return -1;
00485 
00486     buffer[i] = 0;
00487 
00488     return (int)i;
00489 }
00490 
00491 int utils_intCopy(char * buffer,
00492                   size_t length,
00493                   int32_t value)
00494 {
00495 #define _PRV_INT32_MAX_STR_LEN 11
00496     uint8_t str[_PRV_INT32_MAX_STR_LEN];
00497     size_t len;
00498 
00499     len = utils_intToText(value, str, _PRV_INT32_MAX_STR_LEN);
00500     if (len == 0) return -1;
00501     if (len > length + 1) return -1;
00502 
00503     memcpy(buffer, str, len);
00504     buffer[len] = 0;
00505 
00506     return len;
00507 }
00508 
00509 void utils_copyValue(void * dst,
00510                      const void * src,
00511                      size_t len)
00512 {       
00513 #ifdef LWM2M_BIG_ENDIAN
00514     memcpy(dst, src, len);
00515 #else
00516 #ifdef LWM2M_LITTLE_ENDIAN
00517     size_t i;
00518 
00519     for (i = 0; i < len; i++)
00520     {
00521         ((uint8_t *)dst)[i] = ((uint8_t *)src)[len - 1 - i];
00522     }
00523 #endif
00524 #endif
00525 }
00526 
00527 int utils_opaqueToInt(const uint8_t * buffer,
00528                       size_t buffer_len,
00529                       int64_t * dataP)
00530 {
00531     *dataP = 0;
00532 
00533     switch (buffer_len)
00534     {
00535     case 1:
00536     {
00537         *dataP = (int8_t)buffer[0];
00538 
00539         break;
00540     }
00541 
00542     case 2:
00543     {
00544         int16_t value;
00545 
00546         utils_copyValue(&value, buffer, buffer_len);
00547 
00548         *dataP = value;
00549         break;
00550     }
00551 
00552     case 4:
00553     {
00554         int32_t value;
00555 
00556         utils_copyValue(&value, buffer, buffer_len);
00557 
00558         *dataP = value;
00559         break;
00560     }
00561 
00562     case 8:
00563         utils_copyValue(dataP, buffer, buffer_len);
00564         return buffer_len;
00565 
00566     default:
00567         return 0;
00568     }
00569 
00570     return buffer_len;
00571 }
00572 
00573 int utils_opaqueToFloat(const uint8_t * buffer,
00574                         size_t buffer_len,
00575                         double * dataP)
00576 {
00577     switch (buffer_len)
00578     {
00579     case 4:
00580     {
00581         float temp;
00582 
00583         utils_copyValue(&temp, buffer, buffer_len);
00584 
00585         *dataP = temp;
00586     }
00587     return 4;
00588 
00589     case 8:
00590         utils_copyValue(dataP, buffer, buffer_len);
00591         return 8;
00592 
00593     default:
00594         return 0;
00595     }
00596 }
00597 
00598 /**
00599 * Encode an integer value to a byte representation.
00600 * Returns the length of the result. For values < 0xff length is 1,
00601 * for values < 0xffff length is 2 and so on.
00602 * @param data        Input value
00603 * @param data_buffer Result in data_buffer is in big endian encoding
00604 *                    Negative values are represented in two's complement as of
00605 *                    OMA-TS-LightweightM2M-V1_0-20160308-D, Appendix C
00606 */
00607 size_t utils_encodeInt(int64_t data,
00608                        uint8_t data_buffer[_PRV_64BIT_BUFFER_SIZE])
00609 {
00610     size_t length = 0;
00611 
00612     memset(data_buffer, 0, _PRV_64BIT_BUFFER_SIZE);
00613 
00614     if (data >= INT8_MIN && data <= INT8_MAX)
00615     {
00616         length = 1;
00617         data_buffer[0] = data;
00618     }
00619     else if (data >= INT16_MIN && data <= INT16_MAX)
00620     {
00621         int16_t value;
00622 
00623         value = data;
00624         length = 2;
00625         data_buffer[0] = (value >> 8) & 0xFF;
00626         data_buffer[1] = value & 0xFF;
00627     }
00628     else if (data >= INT32_MIN && data <= INT32_MAX)
00629     {
00630         int32_t value;
00631 
00632         value = data;
00633         length = 4;
00634         utils_copyValue(data_buffer, &value, length);
00635     }
00636     else if (data >= INT64_MIN && data <= INT64_MAX)
00637     {
00638         length = 8;
00639         utils_copyValue(data_buffer, &data, length);
00640     }
00641 
00642     return length;
00643 }
00644 
00645 size_t utils_encodeFloat(double data,
00646                          uint8_t data_buffer[_PRV_64BIT_BUFFER_SIZE])
00647 {
00648     size_t length = 0;
00649 
00650     memset(data_buffer, 0, _PRV_64BIT_BUFFER_SIZE);
00651 
00652     if ((data < 0.0 - (double)FLT_MAX) || (data >(double)FLT_MAX))
00653     {
00654         length = 8;
00655         utils_copyValue(data_buffer, &data, 8);
00656     }
00657     else
00658     {
00659         float value;
00660 
00661         length = 4;
00662         value = (float)data;
00663         utils_copyValue(data_buffer, &value, 4);
00664     }
00665 
00666     return length;
00667 }
00668 
00669 #define PRV_B64_PADDING '='
00670 
00671 static char b64Alphabet[64] =
00672 {
00673     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00674     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00675     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00676     'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
00677 };
00678 
00679 static void prv_encodeBlock(uint8_t input[3],
00680                             uint8_t output[4])
00681 {
00682     output[0] = b64Alphabet[input[0] >> 2];
00683     output[1] = b64Alphabet[((input[0] & 0x03) << 4) | (input[1] >> 4)];
00684     output[2] = b64Alphabet[((input[1] & 0x0F) << 2) | (input[2] >> 6)];
00685     output[3] = b64Alphabet[input[2] & 0x3F];
00686 }
00687 
00688 static uint8_t prv_b64Revert(uint8_t value)
00689 {
00690     if (value >= 'A' && value <= 'Z')
00691     {
00692         return (value - 'A');
00693     }
00694     if (value >= 'a' && value <= 'z')
00695     {
00696         return (26 + value - 'a');
00697     }
00698     if (value >= '0' && value <= '9')
00699     {
00700         return (52 + value - '0');
00701     }
00702     switch (value)
00703     {
00704     case '+':
00705         return 62;
00706     case '/':
00707         return 63;
00708     default:
00709         return 0;
00710     }
00711 }
00712 
00713 static void prv_decodeBlock(uint8_t input[4],
00714                             uint8_t output[3])
00715 {
00716     uint8_t tmp[4];
00717     int i;
00718 
00719     memset(output, 0, 3);
00720 
00721     for (i = 0; i < 4; i++)
00722     {
00723         tmp[i] = prv_b64Revert(input[i]);
00724     }
00725 
00726     output[0] = (tmp[0] << 2) | (tmp[1] >> 4);
00727     output[1] = (tmp[1] << 4) | (tmp[2] >> 2);
00728     output[2] = (tmp[2] << 6) | tmp[3];
00729 }
00730 
00731 static size_t prv_getBase64Size(size_t dataLen)
00732 {
00733     size_t result_len;
00734 
00735     result_len = 4 * (dataLen / 3);
00736     if (dataLen % 3) result_len += 4;
00737 
00738     return result_len;
00739 }
00740 
00741 size_t utils_base64Encode(uint8_t * dataP,
00742                           size_t dataLen, 
00743                           uint8_t * bufferP,
00744                           size_t bufferLen)
00745 {
00746     unsigned int data_index;
00747     unsigned int result_index;
00748     size_t result_len;
00749 
00750     result_len = prv_getBase64Size(dataLen);
00751 
00752     if (result_len > bufferLen) return 0;
00753 
00754     data_index = 0;
00755     result_index = 0;
00756     while (data_index < dataLen)
00757     {
00758         switch (dataLen - data_index)
00759         {
00760         case 0:
00761             // should never happen
00762             break;
00763         case 1:
00764             bufferP[result_index] = b64Alphabet[dataP[data_index] >> 2];
00765             bufferP[result_index + 1] = b64Alphabet[(dataP[data_index] & 0x03) << 4];
00766             bufferP[result_index + 2] = PRV_B64_PADDING;
00767             bufferP[result_index + 3] = PRV_B64_PADDING;
00768             break;
00769         case 2:
00770             bufferP[result_index] = b64Alphabet[dataP[data_index] >> 2];
00771             bufferP[result_index + 1] = b64Alphabet[(dataP[data_index] & 0x03) << 4 | (dataP[data_index + 1] >> 4)];
00772             bufferP[result_index + 2] = b64Alphabet[(dataP[data_index + 1] & 0x0F) << 2];
00773             bufferP[result_index + 3] = PRV_B64_PADDING;
00774             break;
00775         default:
00776             prv_encodeBlock(dataP + data_index, bufferP + result_index);
00777             break;
00778         }
00779         data_index += 3;
00780         result_index += 4;
00781     }
00782 
00783     return result_len;
00784 }
00785 
00786 size_t utils_opaqueToBase64(uint8_t * dataP,
00787                             size_t dataLen,
00788                             uint8_t ** bufferP)
00789 {
00790     size_t buffer_len;
00791     size_t result_len;
00792 
00793     buffer_len = prv_getBase64Size(dataLen);
00794 
00795     *bufferP = (uint8_t *)lwm2m_malloc(buffer_len);
00796     if (!*bufferP) return 0;
00797     memset(*bufferP, 0, buffer_len);
00798 
00799     result_len = utils_base64Encode(dataP, dataLen, *bufferP, buffer_len);
00800 
00801     if (result_len == 0)
00802     {
00803         lwm2m_free(*bufferP);
00804         *bufferP = NULL;
00805     }
00806  
00807     return result_len;
00808 }
00809 
00810 size_t utils_base64ToOpaque(uint8_t * dataP,
00811                             size_t dataLen,
00812                             uint8_t ** bufferP)
00813 {
00814     size_t data_index;
00815     size_t result_index;
00816     size_t result_len;
00817 
00818     if (dataLen % 4) return 0;
00819 
00820     result_len = (dataLen >> 2) * 3;
00821     *bufferP = (uint8_t *)lwm2m_malloc(result_len);
00822     if (NULL == *bufferP) return 0;
00823     memset(*bufferP, 0, result_len);
00824 
00825     // remove padding
00826     while (dataP[dataLen - 1] == PRV_B64_PADDING)
00827     {
00828         dataLen--;
00829     }
00830 
00831     data_index = 0;
00832     result_index = 0;
00833     while (data_index < dataLen)
00834     {
00835         prv_decodeBlock(dataP + data_index, *bufferP + result_index);
00836         data_index += 4;
00837         result_index += 3;
00838     }
00839     switch (data_index - dataLen)
00840     {
00841     case 0:
00842         break;
00843     case 2:
00844     {
00845         uint8_t tmp[2];
00846 
00847         tmp[0] = prv_b64Revert(dataP[dataLen - 2]);
00848         tmp[1] = prv_b64Revert(dataP[dataLen - 1]);
00849 
00850         *bufferP[result_index - 3] = (tmp[0] << 2) | (tmp[1] >> 4);
00851         *bufferP[result_index - 2] = (tmp[1] << 4);
00852         result_len -= 2;
00853     }
00854     break;
00855     case 3:
00856     {
00857         uint8_t tmp[3];
00858 
00859         tmp[0] = prv_b64Revert(dataP[dataLen - 3]);
00860         tmp[1] = prv_b64Revert(dataP[dataLen - 2]);
00861         tmp[2] = prv_b64Revert(dataP[dataLen - 1]);
00862 
00863         *bufferP[result_index - 3] = (tmp[0] << 2) | (tmp[1] >> 4);
00864         *bufferP[result_index - 2] = (tmp[1] << 4) | (tmp[2] >> 2);
00865         *bufferP[result_index - 1] = (tmp[2] << 6);
00866         result_len -= 1;
00867     }
00868     break;
00869     default:
00870         // error
00871         lwm2m_free(*bufferP);
00872         *bufferP = NULL;
00873         result_len = 0;
00874         break;
00875     }
00876 
00877     return result_len;
00878 }
00879 
00880 lwm2m_data_type_t utils_depthToDatatype(uri_depth_t depth)
00881 {
00882     switch (depth)
00883     {
00884     case URI_DEPTH_OBJECT:
00885         return LWM2M_TYPE_OBJECT;
00886     case URI_DEPTH_OBJECT_INSTANCE:
00887         return LWM2M_TYPE_OBJECT_INSTANCE;
00888     default:
00889         break;
00890     }
00891 
00892     return LWM2M_TYPE_UNDEFINED;
00893 }