Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mstring.cpp Source File

m2mstring.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed-client/m2mstring.h"
00017 #include <string.h> // strlen
00018 #include <stdlib.h> // malloc, realloc
00019 #include <assert.h>
00020 #include <algorithm> // min
00021 
00022 namespace m2m {
00023 
00024 const String::size_type String::npos = static_cast<size_t>(-1);
00025 
00026 char* String::strdup(const char* s)
00027 {
00028     const size_t len = strlen(s)+1;
00029     char *p2 = static_cast<char*>(malloc(len));
00030     if (p2) {
00031         memcpy(p2, s, len);
00032         allocated_ = len;
00033         size_ = len-1;
00034     }
00035     return p2;
00036 }
00037 
00038 String::String()
00039     : p( strdup("") )
00040 {
00041 }
00042 
00043 String::~String()
00044 {
00045     free(p);
00046     p = 0;
00047 }
00048 
00049 String::String(const String& s)
00050     : p(0)
00051 {
00052     p = static_cast<char*>(malloc(s.size_ + 1));
00053 
00054     allocated_ = s.size_ + 1;
00055     size_      = s.size_;
00056     memcpy(p, s.p, size_ + 1);
00057 }
00058 
00059 String::String(const char* s)
00060     : p(strdup(s))
00061 {
00062 }
00063 
00064 String::String(const char* str, size_t n)
00065 {
00066     p = static_cast<char*>(malloc(n + 1));
00067 
00068     allocated_ = n + 1;
00069     size_      = n;
00070     memcpy(p, str, n);
00071     p[n] = 0;
00072 }
00073 
00074 String& String::operator=(const char* s)
00075 {
00076     if ( p != s ) {
00077         // s could point into our own string, so we have to allocate a new string
00078         const size_t len = strlen(s);
00079         char* copy = (char*) malloc( len + 1);
00080         memmove(copy, s, len+1); // trailing 0
00081         free( p );
00082         p = copy;
00083         size_ = len;
00084         allocated_ = len+1;
00085     }
00086     return *this;
00087 }
00088 
00089 String& String::operator=(const String& s)
00090 {
00091     return operator=(s.p);
00092 }
00093 
00094 String& String::operator+=(const String& s)
00095 {
00096     if (s.size_ > 0) {
00097         this->reserve(size_ + s.size_);
00098         memmove(p+size_, s.p, s.size_+1); // trailing 0
00099         size_ += s.size_;
00100     }
00101     return *this;
00102 }
00103 
00104 // since p and s may overlap, we have to copy our own string first
00105 String& String::operator+=(const char* s)
00106 {
00107     const size_type lens = strlen(s);
00108     if (lens > 0) {
00109         if (size_ + lens + 1 <= allocated_) {
00110             memmove(p+size_, s, lens+1); // trailing 0
00111             size_ += lens;
00112         } else {
00113             String s2( *this );  // copy own data
00114             s2.reserve(size_ + lens);
00115             memmove(s2.p+size_, s, lens+1); // trailing 0
00116             s2.size_ = size_ + lens;
00117             this->swap( s2 );
00118         }
00119     }
00120     return *this;
00121 }
00122 
00123 String& String::operator+=(const char c)
00124 {
00125     push_back(c);
00126     return *this;
00127 }
00128 
00129 void String::push_back(const char c) {
00130 
00131     if (size_ == allocated_ - 1) {
00132         size_t more =  (allocated_* 3) / 2; // factor 1.5
00133         if ( more < 4 ) more = 4;
00134         reserve( size_ + more );
00135     }
00136 
00137     p[size_] = c;
00138     size_++;
00139     p[size_] = 0;
00140 }
00141 
00142 bool String::operator==(const char* s) const
00143 {
00144     if( s == NULL ) {
00145         if( p == NULL ) {
00146             return true;
00147         }
00148         return false;
00149     }
00150     bool ret = strcmp(p, s);
00151     return !ret;
00152 }
00153 
00154 bool String::operator==(const String& s) const
00155 {
00156     bool ret = strcmp(p, s.p);
00157     return !ret;
00158 }
00159 
00160 void String::clear()
00161 {
00162     size_ = 0;
00163     p[0]  = 0;
00164 }
00165 
00166 String String::substr(const size_type pos, size_type length) const
00167 {
00168     String s;
00169     const size_type len = size_;
00170 
00171     if ( pos <= len ) {
00172 
00173         size_type remain = len - pos;
00174 
00175         if ( length > remain )
00176             length = remain;
00177 
00178         s.reserve( length );
00179 
00180         memcpy(s.p, p + pos, length);
00181         s.p[length] = '\0';
00182         s.size_ = length;
00183     }
00184     return s;
00185 }
00186 
00187 
00188 // checked access, accessing the NUL at end is allowed
00189 char String::at(const size_type i) const
00190 {
00191     if ( i <= strlen(p) ) {
00192         return p[i];
00193     } else {
00194         return '\0';
00195     }
00196 }
00197 
00198 String& String::erase(size_type pos, size_type len)
00199 {
00200     if (len > 0) {
00201 
00202         if ( pos < size_ ) { // user must not remove trailing 0
00203 
00204             size_type s2 = size_;
00205             size_type remain = s2 - pos - len;
00206 
00207             if (remain > 0) {
00208                 // erase by overwriting
00209                 memmove(p + pos, p + pos + len, remain);
00210             }
00211 
00212             //if ( remain < 0 ) remain = 0;
00213 
00214             // remove unused space
00215             this->resize( pos+remain );
00216 
00217         }
00218     }
00219     return *this;
00220 }
00221 
00222 String& String::append( const char* str, size_type n) {
00223     if (str && n > 0) {
00224         size_t lens = strlen(str);
00225         if (n > lens)
00226             n = lens;
00227         size_t newlen = size_ + n;
00228         this->reserve( newlen );
00229         memmove(p+size_, str, n); // p and s.p MAY overlap
00230         p[newlen] = 0; // add NUL termination
00231         size_ = newlen;
00232     }
00233     return *this;
00234 }
00235 
00236 String& String::append_raw( const char* str, size_type n) {
00237     if (str && n > 0) {
00238         size_t newlen = size_ + n;
00239         this->reserve( newlen );
00240         memmove(p+size_, str, n); // p and s.p MAY overlap
00241         p[newlen] = 0; // add NUL termination
00242         size_ = newlen;
00243     }
00244     return *this;
00245 }
00246 
00247 void String::append_int(int param) {
00248 
00249     // max len of "-9223372036854775808" plus zero termination
00250     char conv_buff[20+1];
00251 
00252     int len = itoa_c(param, conv_buff);
00253     append_raw(conv_buff, len);
00254 }
00255 
00256 int String::compare( size_type pos, size_type len, const String& str ) const {
00257     int r = -1;
00258     if (pos <= size_) {
00259         if ( len > size_ - pos)
00260             len = size_ - pos; // limit len to available length
00261 
00262         const size_type osize = str.size();
00263         const size_type len2   = std::min(len, osize);
00264         r = strncmp( p + pos, str.p, len2);
00265         if (r==0) // equal so far, now compare sizes
00266             r = len < osize ? -1 : ( len == osize ? 0 : +1 );
00267     }
00268     return r;
00269 }
00270 
00271 int String::compare( size_type pos, size_type len, const char* str ) const {
00272     int r = -1;
00273     if (pos <= size_) {
00274 
00275         if ( len > size_ - pos)
00276             len = size_ - pos; // limit len to available length
00277 
00278         const size_type osize = strlen(str);
00279         const size_type len2   = std::min(len, osize);
00280         r = strncmp( p + pos, str, len2);
00281         if (r==0) // equal so far, now compare sizes
00282             r = len < osize ? -1 : ( len == osize ? 0 : +1 );
00283     }
00284     return r;
00285 }
00286 
00287 int String::find_last_of(char c) const {
00288     int r = -1;
00289     char *v;
00290     v = strrchr(p,c);
00291     if (v != NULL) {
00292         r = 0;
00293         char* i = p;
00294         while (v != i) {
00295             i++;
00296             r++;
00297         }
00298     }
00299     return r;
00300 }
00301 
00302 void String::new_realloc( size_type n) {
00303     if (n > 0 ) {
00304         char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
00305         if (pnew)
00306             p = pnew;
00307     }
00308 }
00309 
00310 void String::reserve( const size_type n) {
00311     if (n >= allocated_ ) {
00312         this->new_realloc(n + 1);
00313         allocated_ = n + 1;
00314     }
00315 }
00316 
00317 void String::resize( const size_type n) {
00318     this->resize( n, 0 );
00319 }
00320 
00321 void String::resize( const size_type n, const char c) {
00322     if (n < size_ ) {
00323         p[n] = 0;
00324         size_ = n;
00325     }
00326     else if (n >  size_ ) {
00327         this->reserve( n );
00328         for (size_type i=size_; i < n; ++i )
00329             p[i] = c;
00330         p[n] = 0;
00331         size_ = n;
00332     }
00333 }
00334 
00335 void String::swap( String& s ) {
00336     std::swap( allocated_, s.allocated_ );
00337     std::swap( size_,      s.size_      );
00338     std::swap( p,          s.p          );
00339 }
00340 
00341 
00342 // Comparison
00343 bool operator<( const String& s1, const String& s2 ) {
00344     return strcmp( s1.c_str(), s2.c_str() ) < 0;
00345 }
00346 
00347 void reverse(char s[], uint32_t length)
00348 {
00349     uint32_t i, j;
00350     char c;
00351 
00352     for (i = 0, j = length-1; i<j; i++, j--) {
00353         c = s[i];
00354         s[i] = s[j];
00355         s[j] = c;
00356     }
00357 }
00358 
00359 uint32_t itoa_c (int64_t n, char s[])
00360 {
00361     int64_t sign;
00362     uint32_t i;
00363 
00364     if ((sign = n) < 0)
00365         n = -n;
00366 
00367     i = 0;
00368 
00369     do {
00370         s[i++] = n % 10 + '0';
00371     }
00372     while ((n /= 10) > 0);
00373 
00374     if (sign < 0)
00375         s[i++] = '-';
00376 
00377     s[i] = '\0';
00378 
00379     m2m::reverse(s, i);
00380     return i;
00381 }
00382 
00383 uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, const uint8_t *array, const uint32_t array_size)
00384 {
00385     uint8_t* buffer = NULL;
00386     size = 0;
00387     if (array) {
00388         value = String::convert_array_to_integer(array, array_size);
00389     }
00390 
00391     if(value < 0xFF) {
00392         size = 1;
00393     } else if(value < 0xFFFF) {
00394         size = 2;
00395     } else if(value < 0xFFFFFF) {
00396         size = 3;
00397     } else if(value < 0xFFFFFFFF) {
00398         size = 4;
00399     } else if(value < 0xFFFFFFFFFF) {
00400         size = 5;
00401     } else if(value < 0xFFFFFFFFFFFF) {
00402         size = 6;
00403     } else if(value < 0xFFFFFFFFFFFFFF) {
00404         size = 7;
00405     } else {
00406         size = 8;
00407     }
00408 
00409     buffer = (uint8_t*)malloc(size);
00410     if (buffer) {
00411         for (int i = 0; i < size; i++) {
00412             buffer[i] = (value >> ((size - i - 1) * 8));
00413         }
00414     } else {
00415         size = 0;
00416     }
00417     return buffer;
00418 }
00419 
00420 int64_t String::convert_array_to_integer(const uint8_t *value, const uint32_t size)
00421 {
00422     int64_t temp_64 = 0;
00423     for (int i = size - 1; i >= 0; i--) {
00424         temp_64 += (uint64_t)(*value++) << i * 8;
00425     }
00426     return temp_64;
00427 }
00428 
00429 } // namespace