sandbox / mbed-client

Fork of mbed-client by Christopher Haster

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     memcpy(p2, s, len);
00031     allocated_ = len;
00032     size_ = len-1;
00033     return p2;
00034 }
00035 
00036 String::String()
00037     : p( strdup("") )
00038 {
00039     _return_value = '\0';
00040 }
00041 
00042 String::~String()
00043 {
00044     free(p);
00045     p = 0;
00046 }
00047 
00048 String::String(const String& s)
00049     : p(0)
00050 {
00051     if( &s != NULL ) {
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     _return_value = '\0';
00059 }
00060 
00061 String::String(const char* s)
00062     : p(strdup(s))
00063 {
00064     _return_value = '\0';
00065 }
00066 
00067 String& String::operator=(const char* s)
00068 {
00069     if ( p != s ) {
00070         // s could point into our own string, so we have to allocate a new string
00071         const size_t len = strlen(s);
00072         char* copy = (char*) malloc( len + 1);
00073         memmove(copy, s, len+1); // trailing 0
00074         free( p );
00075         p = copy;
00076         size_ = len;
00077         allocated_ = len+1;
00078     }
00079     return *this;
00080 }
00081 
00082 String& String::operator=(const String& s)
00083 {
00084     return operator=(s.p);
00085 }
00086 
00087 String& String::operator+=(const String& s)
00088 {
00089     if (s.size_ > 0) {
00090         this->reserve(size_ + s.size_);
00091         memmove(p+size_, s.p, s.size_+1); // trailing 0
00092         size_ += s.size_;
00093     }
00094     return *this;
00095 }
00096 
00097 // since p and s may overlap, we have to copy our own string first
00098 String& String::operator+=(const char* s)
00099 {
00100     const size_type lens = strlen(s);
00101     if (lens > 0) {
00102         if (size_ + lens + 1 <= allocated_) {
00103             memmove(p+size_, s, lens+1); // trailing 0
00104             size_ += lens;
00105         } else {
00106             String s2( *this );  // copy own data
00107             s2.reserve(size_ + lens);
00108             memmove(s2.p+size_, s, lens+1); // trailing 0
00109             s2.size_ = size_ + lens;
00110             this->swap( s2 );
00111         }
00112     }
00113     return *this;
00114 }
00115 
00116 String& String::operator+=(const char c)
00117 {
00118     push_back(c);
00119     return *this;
00120 }
00121 
00122 void String::push_back(const char c) {
00123 
00124     if (size_ == allocated_ - 1) {
00125         size_t more =  (allocated_* 3) / 2; // factor 1.5
00126         if ( more < 4 ) more = 4;
00127         reserve( size_ + more );
00128     }
00129 
00130     p[size_] = c;
00131     size_++;
00132     p[size_] = 0;
00133 }
00134 
00135 bool String::operator==(const char* s) const
00136 {
00137     if( s == NULL ) {
00138         if( p == NULL ) {
00139             return true;
00140         }
00141         return false;
00142     }
00143     bool ret = strcmp(p, s);
00144     return !ret;
00145 }
00146 
00147 bool String::operator==(const String& s) const
00148 {
00149     bool ret = strcmp(p, s.p);
00150     return !ret;
00151 }
00152 
00153 void String::clear()
00154 {
00155     size_ = 0;
00156     p[0]  = 0;
00157 }
00158 
00159 String String::substr(const size_type pos, size_type length) const
00160 {
00161     String s;
00162     const size_type len = size_;
00163 
00164     if ( pos <= len ) {
00165 
00166         size_type remain = len - pos;
00167 
00168         if ( length > remain )
00169             length = remain;
00170 
00171         s.reserve( length );
00172 
00173         memcpy(s.p, p + pos, length);
00174         s.p[length] = '\0';
00175         s.size_ = length;
00176     }
00177     return s;
00178 }
00179 
00180 
00181 // checked access, accessing the NUL at end is allowed
00182 char& String::at(const size_type i)
00183 {
00184     if ( i <= strlen(p) ) {
00185         _return_value = p[i];
00186     } else {
00187         _return_value = '\0';
00188     }
00189     return _return_value;
00190 }
00191 
00192 char String::at(const size_type i) const
00193 {
00194     if ( i <= strlen(p) ) {
00195         return p[i];
00196     } else {
00197         return '\0';
00198     }
00199 }
00200 
00201 String& String::erase(size_type pos, size_type len)
00202 {
00203     if (len > 0) {
00204 
00205         if ( pos < size_ ) { // user must not remove trailing 0
00206 
00207             size_type s2 = size_;
00208             size_type remain = s2 - pos - len;
00209 
00210             if (remain > 0) {
00211                 // erase by overwriting
00212                 memmove(p + pos, p + pos + len, remain);
00213             }
00214 
00215             //if ( remain < 0 ) remain = 0;
00216 
00217             // remove unused space
00218             this->resize( pos+remain );
00219 
00220         }
00221     }
00222     return *this;
00223 }
00224 
00225 String& String::append( const char* str, size_type n) {
00226     if (str && n > 0) {
00227         size_t lens = strlen(str);
00228         if (n > lens)
00229             n = lens;
00230         size_t newlen = size_ + n;
00231         this->reserve( newlen );
00232         memmove(p+size_, str, n); // p and s.p MAY overlap
00233         p[newlen] = 0; // add NUL termination
00234         size_ = newlen;
00235     }
00236     return *this;
00237 }
00238 
00239 int String::compare( size_type pos, size_type len, const String& str ) const {
00240     int r = -1;
00241     if (pos <= size_) {
00242         if ( len > size_ - pos)
00243             len = size_ - pos; // limit len to available length
00244 
00245         const size_type osize = str.size();
00246         const size_type len2   = std::min(len, osize);
00247         r = strncmp( p + pos, str.p, len2);
00248         if (r==0) // equal so far, now compare sizes
00249             r = len < osize ? -1 : ( len == osize ? 0 : +1 );
00250     }
00251     return r;
00252 }
00253 
00254 int String::compare( size_type pos, size_type len, const char* str ) const {
00255     int r = -1;
00256     if (pos <= size_) {
00257 
00258         if ( len > size_ - pos)
00259             len = size_ - pos; // limit len to available length
00260 
00261         const size_type osize = strlen(str);
00262         const size_type len2   = std::min(len, osize);
00263         r = strncmp( p + pos, str, len2);
00264         if (r==0) // equal so far, now compare sizes
00265             r = len < osize ? -1 : ( len == osize ? 0 : +1 );
00266     }
00267     return r;
00268 }
00269 
00270 int String::find_last_of(char c) const {
00271     int r = -1;
00272     char *v;
00273     v = strrchr(p,c);
00274     if (v != NULL) {
00275         r = 0;
00276         char* i = p;
00277         while (v != i) {
00278             i++;
00279             r++;
00280         }
00281     }
00282     return r;
00283 }
00284 
00285 void String::new_realloc( size_type n) {
00286     if (n > 0 ) {
00287         char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
00288         if (pnew)
00289             p = pnew;
00290     }
00291 }
00292 
00293 void String::reserve( const size_type n) {
00294     if (n >= allocated_ ) {
00295         this->new_realloc(n + 1);
00296         allocated_ = n + 1;
00297     }
00298 }
00299 
00300 void String::resize( const size_type n) {
00301     this->resize( n, 0 );
00302 }
00303 
00304 void String::resize( const size_type n, const char c) {
00305     if (n < size_ ) {
00306         p[n] = 0;
00307         size_ = n;
00308     }
00309     else if (n >  size_ ) {
00310         this->reserve( n );
00311         for (size_type i=size_; i < n; ++i )
00312             p[i] = c;
00313         p[n] = 0;
00314         size_ = n;
00315     }
00316 }
00317 
00318 void String::swap( String& s ) {
00319     std::swap( allocated_, s.allocated_ );
00320     std::swap( size_,      s.size_      );
00321     std::swap( p,          s.p          );
00322 }
00323 
00324 
00325 // Comparison
00326 bool operator<( const String& s1, const String& s2 ) {
00327     return strcmp( s1.c_str(), s2.c_str() ) < 0;
00328 }
00329 
00330 void reverse(char s[], uint32_t length)
00331 {
00332     uint32_t i, j;
00333     char c;
00334 
00335     for (i = 0, j = length-1; i<j; i++, j--) {
00336         c = s[i];
00337         s[i] = s[j];
00338         s[j] = c;
00339     }
00340 }
00341 
00342 uint32_t itoa_c (int64_t n, char s[])
00343 {
00344     int64_t sign;
00345     uint32_t i;
00346 
00347     if ((sign = n) < 0)
00348         n = -n;
00349 
00350     i = 0;
00351 
00352     do {
00353         s[i++] = n % 10 + '0';
00354     }
00355     while ((n /= 10) > 0);
00356 
00357     if (sign < 0)
00358         s[i++] = '-';
00359 
00360     s[i] = '\0';
00361 
00362     m2m::reverse(s, i);
00363     return i;
00364 }
00365 
00366 uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, uint8_t *array, uint32_t array_size)
00367 {
00368     uint8_t* buffer = NULL;
00369     size = 0;
00370     if (array) {
00371         value = String::convert_array_to_integer(array, array_size);
00372     }
00373 
00374     if(value < 0xFF) {
00375         size = 1;
00376     } else if(value < 0xFFFF) {
00377         size = 2;
00378     } else if(value < 0xFFFFFF) {
00379         size = 3;
00380     } else if(value < 0xFFFFFFFF) {
00381         size = 4;
00382     } else if(value < 0xFFFFFFFFFF) {
00383         size = 5;
00384     } else if(value < 0xFFFFFFFFFFFF) {
00385         size = 6;
00386     } else if(value < 0xFFFFFFFFFFFFFF) {
00387         size = 7;
00388     } else {
00389         size = 8;
00390     }
00391 
00392     buffer = (uint8_t*)malloc(size);
00393     if (buffer) {
00394         for (int i = 0; i < size; i++) {
00395             buffer[i] = (value >> ((size - i - 1) * 8));
00396         }
00397     } else {
00398         size = 0;
00399     }
00400     return buffer;
00401 }
00402 
00403 int64_t String::convert_array_to_integer(uint8_t *value, uint32_t size)
00404 {
00405     int64_t temp_64 = 0;
00406     for (int i = size - 1; i >= 0; i--) {
00407         temp_64 += (uint64_t)(*value++) << i * 8;
00408     }
00409     return temp_64;
00410 }
00411 
00412 } // namespace