mbed client lightswitch demo
Dependencies: mbed Socket lwip-eth lwip-sys lwip
Fork of mbed-client-classic-example-lwip by
mbed-client/source/m2mstring.cpp
- Committer:
- mbedAustin
- Date:
- 2016-06-09
- Revision:
- 11:cada08fc8a70
File content as of revision 11:cada08fc8a70:
/*
* Copyright (c) 2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbed-client/m2mstring.h"
#include <string.h> // strlen
#include <stdlib.h> // malloc, realloc
#include <assert.h>
#include <algorithm> // min
namespace m2m {
const String::size_type String::npos = static_cast<size_t>(-1);
/*
* Like the 'new' operator, we want to guarantee that we NEVER
* return NULL. Loop until there is free memory.
*
*/
static char* malloc_never_null(const size_t b)
{
char *p;
do {
p = static_cast<char*>(malloc(b));
} while ( p == NULL );
return p;
}
/**
* Allocates memory for the copy the string at the same time sets "this->allocated".
* @param s
* @return
*/
char*
String::strdup_never_null(const char* s)
{
const size_t len = strlen(s)+1;
char *p2 = malloc_never_null(len);
memcpy(p2, s, len);
allocated_=len;
size_=len-1;
return p2;
}
String::String()
: p( strdup_never_null("") )
{
_return_value = '\0';
}
String::~String()
{
free(p);
p = 0;
}
String::String(const String& s)
: p(0)
{
if( &s != NULL ){
p = malloc_never_null( s.size_ + 1 ); // copy only used part
allocated_ = s.size_ + 1;
size_ = s.size_;
memcpy(p, s.p, size_ + 1);
}
_return_value = '\0';
}
String::String(const char* s)
: p(strdup_never_null(s))
{
_return_value = '\0';
}
String& String::operator=(const char* s)
{
if ( p != s ) {
// s could point into our own string, so we have to allocate a new string
const size_t len = strlen(s);
char* copy = (char*) malloc( len + 1);
memmove(copy, s, len+1); // trailing 0
free( p );
p = copy;
size_ = len;
allocated_ = len+1;
}
return *this;
}
String& String::operator=(const String& s)
{
return operator=(s.p);
}
String& String::operator+=(const String& s)
{
if (s.size_ > 0){
this->reserve(size_ + s.size_);
memmove(p+size_, s.p, s.size_+1); // trailing 0
size_ += s.size_;
}
return *this;
}
// since p and s may overlap, we have to copy our own string first
String& String::operator+=(const char* s)
{
const size_type lens = strlen(s);
if (lens > 0){
if (size_ + lens + 1 <= allocated_) {
memmove(p+size_, s, lens+1); // trailing 0
size_ += lens;
} else {
String s2( *this ); // copy own data
s2.reserve(size_ + lens);
memmove(s2.p+size_, s, lens+1); // trailing 0
s2.size_ = size_ + lens;
this->swap( s2 );
}
}
return *this;
}
String& String::operator+=(const char c)
{
push_back(c);
return *this;
}
void String::push_back(const char c) {
if (size_ == allocated_ - 1) {
size_t more = (allocated_* 3) / 2; // factor 1.5
if ( more < 4 ) more = 4;
reserve( size_ + more );
}
p[size_] = c;
size_++;
p[size_] = 0;
}
bool String::operator==(const char* s) const
{
if( s == NULL ){
if( p == NULL ){
return true;
}
return false;
}
bool ret = strcmp(p, s);
return !ret;
}
bool String::operator==(const String& s) const
{
bool ret = strcmp(p, s.p);
return !ret;
}
void String::clear()
{
size_ = 0;
p[0] = 0;
}
// String operator+(const String& lhs, const String& rhs)
// {
// return String(lhs) += rhs;
// }
String String::substr(const size_type pos, size_type length) const
{
String s;
const size_type len = size_;
if ( pos <= len ) {
size_type remain = len - pos;
if ( length > remain )
length = remain;
s.reserve( length );
memcpy(s.p, p + pos, length);
s.p[length] = '\0';
s.size_ = length;
}
return s;
}
// checked access, accessing the NUL at end is allowed
char& String::at(const size_type i)
{
if ( i <= strlen(p) ) {
_return_value = p[i];
} else {
_return_value = '\0';
}
return _return_value;
}
char String::at(const size_type i) const
{
if ( i <= strlen(p) ) {
return p[i];
} else {
return '\0';
}
}
String& String::erase(size_type pos, size_type len)
{
if (len > 0) {
if ( pos < size_ ) { // user must not remove trailing 0
size_type s2 = size_;
size_type remain = s2 - pos - len;
if (remain > 0) {
// erase by overwriting
memmove(p + pos, p + pos + len, remain);
}
//if ( remain < 0 ) remain = 0;
// remove unused space
this->resize( pos+remain );
}
}
return *this;
}
String& String::append( const char* str, size_type n) {
if (str && n > 0) {
size_t lens = strlen(str);
if (n > lens)
n = lens;
size_t newlen = size_ + n;
this->reserve( newlen );
memmove(p+size_, str, n); // p and s.p MAY overlap
p[newlen] = 0; // add NUL termination
size_ = newlen;
}
return *this;
}
int
String::compare( size_type pos, size_type len, const String& str ) const {
int r = -1;
if (pos <= size_) {
if ( len > size_ - pos)
len = size_ - pos; // limit len to available length
const size_type osize = str.size();
const size_type len2 = std::min(len, osize);
r = strncmp( p + pos, str.p, len2);
if (r==0) // equal so far, now compare sizes
r = len < osize ? -1 : ( len == osize ? 0 : +1 );
}
return r;
}
int
String::compare( size_type pos, size_type len, const char* str ) const {
int r = -1;
if (pos <= size_) {
if ( len > size_ - pos)
len = size_ - pos; // limit len to available length
const size_type osize = strlen(str);
const size_type len2 = std::min(len, osize);
r = strncmp( p + pos, str, len2);
if (r==0) // equal so far, now compare sizes
r = len < osize ? -1 : ( len == osize ? 0 : +1 );
}
return r;
}
int
String::find_last_of(char c) const {
int r = -1;
char *v;
v = strrchr(p,c);
if (v != NULL){
r = 0;
char* i = p;
while (v != i){
i++;
r++;
}
}
return r;
}
void
String::new_realloc( size_type n) {
if (n > 0 ) {
char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
if (pnew)
p = pnew;
}
}
void
String::reserve( const size_type n) {
if (n >= allocated_ ) {
this->new_realloc(n + 1);
allocated_ = n + 1;
}
}
void
String::resize( const size_type n) {
this->resize( n, 0 );
}
void
String::resize( const size_type n, const char c) {
if (n < size_ ) {
p[n] = 0;
size_ = n;
}
else if (n > size_ ) {
this->reserve( n );
for (size_type i=size_; i < n; ++i )
p[i] = c;
p[n] = 0;
size_ = n;
}
}
void String::swap( String& s ) {
std::swap( allocated_, s.allocated_ );
std::swap( size_, s.size_ );
std::swap( p, s.p );
}
// Comparison
bool operator<( const String& s1, const String& s2 ) {
return strcmp( s1.c_str(), s2.c_str() ) < 0;
}
} // namespace
Austin Blackstone
