Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FXAS21002 FXOS8700Q
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 00021 namespace m2m { 00022 00023 00024 // can't use std::min as it is not universally available 00025 #ifndef MIN 00026 #define MIN(A,B) ((A) < (B) ? (A) : (B)) 00027 #endif 00028 00029 const String::size_type String::npos = static_cast<size_t>(-1); 00030 00031 char* String::strdup(const char* s) 00032 { 00033 const size_t len = strlen(s)+1; 00034 char *p2 = static_cast<char*>(malloc(len)); 00035 if (p2) { 00036 memcpy(p2, s, len); 00037 allocated_ = len; 00038 size_ = len-1; 00039 } 00040 return p2; 00041 } 00042 00043 String::String() 00044 : p( strdup("") ) 00045 { 00046 } 00047 00048 String::~String() 00049 { 00050 free(p); 00051 p = 0; 00052 } 00053 00054 String::String(const String& s) 00055 : p(0) 00056 { 00057 p = static_cast<char*>(malloc(s.size_ + 1)); 00058 00059 allocated_ = s.size_ + 1; 00060 size_ = s.size_; 00061 memcpy(p, s.p, size_ + 1); 00062 } 00063 00064 String::String(const char* s) 00065 : p(strdup(s)) 00066 { 00067 } 00068 00069 String::String(const char* str, size_t n) 00070 { 00071 p = static_cast<char*>(malloc(n + 1)); 00072 00073 allocated_ = n + 1; 00074 size_ = n; 00075 memcpy(p, str, n); 00076 p[n] = 0; 00077 } 00078 00079 String& String::operator=(const char* s) 00080 { 00081 if ( p != s ) { 00082 // s could point into our own string, so we have to allocate a new string 00083 const size_t len = strlen(s); 00084 char* copy = (char*) malloc( len + 1); 00085 memmove(copy, s, len+1); // trailing 0 00086 free( p ); 00087 p = copy; 00088 size_ = len; 00089 allocated_ = len+1; 00090 } 00091 return *this; 00092 } 00093 00094 String& String::operator=(const String& s) 00095 { 00096 return operator=(s.p); 00097 } 00098 00099 String& String::operator+=(const String& s) 00100 { 00101 if (s.size_ > 0) { 00102 this->reserve(size_ + s.size_); 00103 memmove(p+size_, s.p, s.size_+1); // trailing 0 00104 size_ += s.size_; 00105 } 00106 return *this; 00107 } 00108 00109 // since p and s may overlap, we have to copy our own string first 00110 String& String::operator+=(const char* s) 00111 { 00112 const size_type lens = strlen(s); 00113 if (lens > 0) { 00114 if (size_ + lens + 1 <= allocated_) { 00115 memmove(p+size_, s, lens+1); // trailing 0 00116 size_ += lens; 00117 } else { 00118 String s2( *this ); // copy own data 00119 s2.reserve(size_ + lens); 00120 memmove(s2.p+size_, s, lens+1); // trailing 0 00121 s2.size_ = size_ + lens; 00122 this->swap( s2 ); 00123 } 00124 } 00125 return *this; 00126 } 00127 00128 String& String::operator+=(const char c) 00129 { 00130 push_back(c); 00131 return *this; 00132 } 00133 00134 void String::push_back(const char c) { 00135 00136 if (size_ == allocated_ - 1) { 00137 size_t more = (allocated_* 3) / 2; // factor 1.5 00138 if ( more < 4 ) more = 4; 00139 reserve( size_ + more ); 00140 } 00141 00142 p[size_] = c; 00143 size_++; 00144 p[size_] = 0; 00145 } 00146 00147 bool String::operator==(const char* s) const 00148 { 00149 if( s == NULL ) { 00150 if( p == NULL ) { 00151 return true; 00152 } 00153 return false; 00154 } 00155 bool ret = strcmp(p, s); 00156 return !ret; 00157 } 00158 00159 bool String::operator==(const String& s) const 00160 { 00161 bool ret = strcmp(p, s.p); 00162 return !ret; 00163 } 00164 00165 void String::clear() 00166 { 00167 size_ = 0; 00168 p[0] = 0; 00169 } 00170 00171 String String::substr(const size_type pos, size_type length) const 00172 { 00173 String s; 00174 const size_type len = size_; 00175 00176 if ( pos <= len ) { 00177 00178 size_type remain = len - pos; 00179 00180 if ( length > remain ) 00181 length = remain; 00182 00183 s.reserve( length ); 00184 00185 memcpy(s.p, p + pos, length); 00186 s.p[length] = '\0'; 00187 s.size_ = length; 00188 } 00189 return s; 00190 } 00191 00192 00193 // checked access, accessing the NUL at end is allowed 00194 char String::at(const size_type i) const 00195 { 00196 if ( i <= strlen(p) ) { 00197 return p[i]; 00198 } else { 00199 return '\0'; 00200 } 00201 } 00202 00203 String& String::erase(size_type pos, size_type len) 00204 { 00205 if (len > 0) { 00206 00207 if ( pos < size_ ) { // user must not remove trailing 0 00208 00209 size_type s2 = size_; 00210 size_type remain = s2 - pos - len; 00211 00212 if (remain > 0) { 00213 // erase by overwriting 00214 memmove(p + pos, p + pos + len, remain); 00215 } 00216 00217 //if ( remain < 0 ) remain = 0; 00218 00219 // remove unused space 00220 this->resize( pos+remain ); 00221 00222 } 00223 } 00224 return *this; 00225 } 00226 00227 String& String::append( const char* str, size_type n) { 00228 if (str && n > 0) { 00229 size_t lens = strlen(str); 00230 if (n > lens) 00231 n = lens; 00232 size_t newlen = size_ + n; 00233 this->reserve( newlen ); 00234 memmove(p+size_, str, n); // p and s.p MAY overlap 00235 p[newlen] = 0; // add NUL termination 00236 size_ = newlen; 00237 } 00238 return *this; 00239 } 00240 00241 String& String::append_raw( const char* str, size_type n) { 00242 if (str && n > 0) { 00243 size_t newlen = size_ + n; 00244 this->reserve( newlen ); 00245 memmove(p+size_, str, n); // p and s.p MAY overlap 00246 p[newlen] = 0; // add NUL termination 00247 size_ = newlen; 00248 } 00249 return *this; 00250 } 00251 00252 void String::append_int(int param) { 00253 00254 // max len of "-9223372036854775808" plus zero termination 00255 char conv_buff[20+1]; 00256 00257 int len = itoa_c(param, conv_buff); 00258 append_raw(conv_buff, len); 00259 } 00260 00261 int String::compare( size_type pos, size_type len, const String& str ) const { 00262 int r = -1; 00263 if (pos <= size_) { 00264 if ( len > size_ - pos) 00265 len = size_ - pos; // limit len to available length 00266 00267 const size_type osize = str.size(); 00268 const size_type len2 = MIN(len, osize); 00269 r = strncmp( p + pos, str.p, len2); 00270 if (r==0) // equal so far, now compare sizes 00271 r = len < osize ? -1 : ( len == osize ? 0 : +1 ); 00272 } 00273 return r; 00274 } 00275 00276 int String::compare( size_type pos, size_type len, const char* str ) const { 00277 int r = -1; 00278 if (pos <= size_) { 00279 00280 if ( len > size_ - pos) 00281 len = size_ - pos; // limit len to available length 00282 00283 const size_type osize = strlen(str); 00284 const size_type len2 = MIN(len, osize); 00285 r = strncmp( p + pos, str, len2); 00286 if (r==0) // equal so far, now compare sizes 00287 r = len < osize ? -1 : ( len == osize ? 0 : +1 ); 00288 } 00289 return r; 00290 } 00291 00292 int String::find_last_of(char c) const { 00293 int r = -1; 00294 char *v; 00295 v = strrchr(p,c); 00296 if (v != NULL) { 00297 r = 0; 00298 char* i = p; 00299 while (v != i) { 00300 i++; 00301 r++; 00302 } 00303 } 00304 return r; 00305 } 00306 00307 void String::new_realloc( size_type n) { 00308 if (n > 0 ) { 00309 char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL 00310 if (pnew) 00311 p = pnew; 00312 } 00313 } 00314 00315 void String::reserve( const size_type n) { 00316 if (n >= allocated_ ) { 00317 this->new_realloc(n + 1); 00318 allocated_ = n + 1; 00319 } 00320 } 00321 00322 void String::resize( const size_type n) { 00323 this->resize( n, 0 ); 00324 } 00325 00326 void String::resize( const size_type n, const char c) { 00327 if (n < size_ ) { 00328 p[n] = 0; 00329 size_ = n; 00330 } 00331 else if (n > size_ ) { 00332 this->reserve( n ); 00333 for (size_type i=size_; i < n; ++i ) 00334 p[i] = c; 00335 p[n] = 0; 00336 size_ = n; 00337 } 00338 } 00339 00340 void String::swap(String& s) { 00341 00342 // do the swap manually, without relience on std::swap() as that is not always available 00343 size_t temp; 00344 char* tempPtr; 00345 00346 temp = allocated_; 00347 allocated_ = s.allocated_; 00348 s.allocated_ = temp; 00349 00350 temp = size_; 00351 size_ = s.size_; 00352 s.size_ = temp; 00353 00354 tempPtr = p; 00355 p = s.p; 00356 s.p = tempPtr; 00357 } 00358 00359 00360 // Comparison 00361 bool operator<( const String& s1, const String& s2 ) { 00362 return strcmp( s1.c_str(), s2.c_str() ) < 0; 00363 } 00364 00365 void reverse(char s[], uint32_t length) 00366 { 00367 uint32_t i, j; 00368 char c; 00369 00370 for (i = 0, j = length-1; i<j; i++, j--) { 00371 c = s[i]; 00372 s[i] = s[j]; 00373 s[j] = c; 00374 } 00375 } 00376 00377 uint32_t itoa_c (int64_t n, char s[]) 00378 { 00379 int64_t sign; 00380 uint32_t i; 00381 00382 if ((sign = n) < 0) 00383 n = -n; 00384 00385 i = 0; 00386 00387 do { 00388 s[i++] = n % 10 + '0'; 00389 } 00390 while ((n /= 10) > 0); 00391 00392 if (sign < 0) 00393 s[i++] = '-'; 00394 00395 s[i] = '\0'; 00396 00397 m2m::reverse(s, i); 00398 return i; 00399 } 00400 00401 uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, const uint8_t *array, const uint32_t array_size) 00402 { 00403 uint8_t* buffer = NULL; 00404 size = 0; 00405 if (array) { 00406 value = String::convert_array_to_integer(array, array_size); 00407 } 00408 00409 if(value < 0xFF) { 00410 size = 1; 00411 } else if(value < 0xFFFF) { 00412 size = 2; 00413 } else if(value < 0xFFFFFF) { 00414 size = 3; 00415 } else if(value < 0xFFFFFFFF) { 00416 size = 4; 00417 } else if(value < 0xFFFFFFFFFF) { 00418 size = 5; 00419 } else if(value < 0xFFFFFFFFFFFF) { 00420 size = 6; 00421 } else if(value < 0xFFFFFFFFFFFFFF) { 00422 size = 7; 00423 } else { 00424 size = 8; 00425 } 00426 00427 buffer = (uint8_t*)malloc(size); 00428 if (buffer) { 00429 for (int i = 0; i < size; i++) { 00430 buffer[i] = (value >> ((size - i - 1) * 8)); 00431 } 00432 } else { 00433 size = 0; 00434 } 00435 return buffer; 00436 } 00437 00438 int64_t String::convert_array_to_integer(const uint8_t *value, const uint32_t size) 00439 { 00440 int64_t temp_64 = 0; 00441 for (int i = size - 1; i >= 0; i--) { 00442 temp_64 += (uint64_t)(*value++) << i * 8; 00443 } 00444 return temp_64; 00445 } 00446 00447 bool String::convert_ascii_to_int(const char *value, size_t length, int64_t &conversion_result) 00448 { 00449 unsigned int index = 0; 00450 00451 int64_t result = 0; 00452 00453 int sign; 00454 00455 int digit; 00456 00457 // return value, will be set to true if at least one digit is found 00458 // and a false is returned if 00459 // a) no digits found, ie. string is empty 00460 // b) a non-digit or non-'+' or non-'-' char is found. 00461 // c) more than one +, - chars are found 00462 // 00463 bool success = false; 00464 00465 // have predictable output value even on error 00466 conversion_result = 0; 00467 00468 // the optional sign needs to be the first char 00469 if ((length > 0) && (value[index] == '+')) { 00470 sign = 1; 00471 index++; 00472 } else if ((length > 0) && (value[index] == '-')) { 00473 sign = -1; 00474 index++; 00475 } else { 00476 sign = 1; 00477 } 00478 00479 while ((index < length) && (value[index] != 0)) { 00480 00481 const char c = value[index++]; 00482 00483 switch (c) { 00484 00485 case '0': 00486 case '1': 00487 case '2': 00488 case '3': 00489 case '4': 00490 case '5': 00491 case '6': 00492 case '7': 00493 case '8': 00494 case '9': 00495 digit = c - '0'; 00496 result *= 10; 00497 result += digit; 00498 success = true; // at least one digit was converted successfully 00499 break; 00500 00501 // there can be only one sign char and it must be the first 00502 case '+': 00503 case '-': 00504 default: 00505 // Note: the handling of having a number with digits in front and 00506 // non-digits at end (eg. "0zero") differs from sscanf() on glibc, 00507 // as sscanf will return what it got converted and a success value 00508 // even if the string ended with junk. 00509 conversion_result = 0; 00510 return false; 00511 } 00512 } 00513 00514 // put the sign in place 00515 result *= sign; 00516 00517 // and pass the result to caller 00518 conversion_result = result; 00519 00520 return success; 00521 } 00522 00523 } // namespace
Generated on Tue Jul 12 2022 20:21:00 by
