Timothy Beight / Mbed 2 deprecated 6_songs-from-the-cloud

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

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