From d179695b0494b96cc1feb963905ee8fea9a7d2a5 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 27 Oct 2015 15:41:24 +0100 Subject: [PATCH 1/4] Add new/delete implementations This is needed to pass C++ validation in test suite --- cores/arduino/WString.h | 2 +- cores/arduino/new.cpp | 43 +++++++++++++++++++++++++++++++++++++++++ cores/arduino/new.h | 33 +++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 cores/arduino/new.cpp create mode 100644 cores/arduino/new.h diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h index cfade3d1..cd90253c 100644 --- a/cores/arduino/WString.h +++ b/cores/arduino/WString.h @@ -31,7 +31,7 @@ #include #include #include "stdlib_noniso.h" -//#include +#include // When compiling programs with this class, the following gcc parameters // dramatically increase performance and memory (RAM) efficiency, typically diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp new file mode 100644 index 00000000..e9cbed33 --- /dev/null +++ b/cores/arduino/new.cpp @@ -0,0 +1,43 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include "new.h" + +void *operator new(size_t size) { + return malloc(size); +} + +void *operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void * ptr) { + free(ptr); +} + +void operator delete[](void * ptr) { + free(ptr); +} + +extern "C" { + __extension__ typedef int __guard __attribute__((mode (__DI__))); + + int __cxa_guard_acquire(__guard g) {return !(char )(g);}; + void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; +}; diff --git a/cores/arduino/new.h b/cores/arduino/new.h new file mode 100644 index 00000000..aea1e9b0 --- /dev/null +++ b/cores/arduino/new.h @@ -0,0 +1,33 @@ +/* + Copyright (c) 2014 Arduino. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef NEW_H +#define NEW_H + +#ifdef __cplusplus + +#include + +void * operator new(size_t size); +void * operator new[](size_t size); +void operator delete(void * ptr); +void operator delete[](void * ptr); + +#endif +#endif + From c8ecd5f0af6c87fdd02382f0cab275d83da31f2c Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 27 Oct 2015 18:01:17 +0100 Subject: [PATCH 2/4] Sync IPAddress and Wstring with SAM implementation Test suite failed on these functions --- cores/arduino/IPAddress.cpp | 42 ++++++++++++++++++ cores/arduino/IPAddress.h | 7 ++- cores/arduino/WString.cpp | 87 ++++++++++++++++++++++++++----------- cores/arduino/WString.h | 16 ++++--- 4 files changed, 119 insertions(+), 33 deletions(-) diff --git a/cores/arduino/IPAddress.cpp b/cores/arduino/IPAddress.cpp index 899cbd4e..76aefa8b 100644 --- a/cores/arduino/IPAddress.cpp +++ b/cores/arduino/IPAddress.cpp @@ -43,6 +43,48 @@ IPAddress::IPAddress(const uint8_t *address) memcpy(_address.bytes, address, sizeof(_address.bytes)); } +bool IPAddress::fromString(const char *address) +{ + // TODO: add support for "a", "a.b", "a.b.c" formats + + uint16_t acc = 0; // Accumulator + uint8_t dots = 0; + + while (*address) + { + char c = *address++; + if (c >= '0' && c <= '9') + { + acc = acc * 10 + (c - '0'); + if (acc > 255) { + // Value out of [0..255] range + return false; + } + } + else if (c == '.') + { + if (dots == 3) { + // Too much dots (there must be 3 dots) + return false; + } + _address.bytes[dots++] = acc; + acc = 0; + } + else + { + // Invalid char + return false; + } + } + + if (dots != 3) { + // Too few dots (there must be 3 dots) + return false; + } + _address.bytes[3] = acc; + return true; +} + IPAddress& IPAddress::operator=(const uint8_t *address) { memcpy(_address.bytes, address, sizeof(_address.bytes)); diff --git a/cores/arduino/IPAddress.h b/cores/arduino/IPAddress.h index 94acdc45..d762f2c0 100644 --- a/cores/arduino/IPAddress.h +++ b/cores/arduino/IPAddress.h @@ -21,7 +21,8 @@ #define IPAddress_h #include -#include +#include "Printable.h" +#include "WString.h" // A class to make it easier to handle and pass around IP addresses @@ -45,6 +46,9 @@ class IPAddress : public Printable { IPAddress(uint32_t address); IPAddress(const uint8_t *address); + bool fromString(const char *address); + bool fromString(const String &address) { return fromString(address.c_str()); } + // Overloaded cast operator to allow IPAddress objects to be used where a pointer // to a four-byte uint8_t array is expected operator uint32_t() const { return _address.dword; }; @@ -71,5 +75,4 @@ class IPAddress : public Printable { const IPAddress INADDR_NONE(0,0,0,0); - #endif diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index 7b0082a2..a604d2a7 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -31,15 +31,7 @@ #include -// following the C++ standard operators with attributes in right -// side must be defined globally -String operator + ( const char *cstr, const String &str_arg) -{ - String &str_arg_o = const_cast(str_arg); - String aux = String(cstr); - aux.concat(str_arg_o); - return aux; -} + /*********************************************/ /* Constructors */ /*********************************************/ @@ -56,7 +48,13 @@ String::String(const String &value) *this = value; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String::String(const __FlashStringHelper *pstr) +{ + init(); + *this = pstr; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) String::String(String &&rval) { init(); @@ -162,7 +160,6 @@ inline void String::init(void) buffer = NULL; capacity = 0; len = 0; - flags = 0; } void String::invalidate(void) @@ -197,18 +194,29 @@ unsigned char String::changeBuffer(unsigned int maxStrLen) /* Copy and Move */ /*********************************************/ -String & String::copy(const char *cstr, unsigned int _length) +String & String::copy(const char *cstr, unsigned int length) { - if (!reserve(_length)) { + if (!reserve(length)) { invalidate(); return *this; } - len = _length; + len = length; strcpy(buffer, cstr); return *this; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ +String & String::copy(const __FlashStringHelper *pstr, unsigned int length) +{ + if (!reserve(length)) { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + return *this; +} + +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) void String::move(String &rhs) { if (buffer) { @@ -240,7 +248,7 @@ String & String::operator = (const String &rhs) return *this; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) String & String::operator = (String &&rval) { if (this != &rval) move(rval); @@ -262,6 +270,14 @@ String & String::operator = (const char *cstr) return *this; } +String & String::operator = (const __FlashStringHelper *pstr) +{ + if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + else invalidate(); + + return *this; +} + /*********************************************/ /* concat */ /*********************************************/ @@ -359,6 +375,18 @@ unsigned char String::concat(double num) return concat(string, strlen(string)); } +unsigned char String::concat(const __FlashStringHelper * str) +{ + if (!str) return 0; + int length = strlen_P((const char *) str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (const char *) str); + len = newlen; + return 1; +} + /*********************************************/ /* Concatenate */ /*********************************************/ @@ -447,6 +475,13 @@ StringSumHelper & operator + (const StringSumHelper &lhs, double num) return a; } +StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +{ + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; +} + /*********************************************/ /* Comparison */ /*********************************************/ @@ -639,7 +674,7 @@ String String::substring(unsigned int left, unsigned int right) const left = temp; } String out; - if (left > len) return out; + if (left >= len) return out; if (right > len) right = len; char temp = buffer[right]; // save the replaced character buffer[right] = '\0'; @@ -652,24 +687,24 @@ String String::substring(unsigned int left, unsigned int right) const /* Modification */ /*********************************************/ -void String::replace(char find, char _replace) +void String::replace(char find, char replace) { if (!buffer) return; for (char *p = buffer; *p; p++) { - if (*p == find) *p = _replace; + if (*p == find) *p = replace; } } -void String::replace(const String& find, const String& _replace) +void String::replace(const String& find, const String& replace) { if (len == 0 || find.len == 0) return; - int diff = _replace.len - find.len; + int diff = replace.len - find.len; char *readFrom = buffer; char *foundAt; if (diff == 0) { while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, _replace.buffer, _replace.len); - readFrom = foundAt + _replace.len; + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; } } else if (diff < 0) { char *writeTo = buffer; @@ -677,8 +712,8 @@ void String::replace(const String& find, const String& _replace) unsigned int n = foundAt - readFrom; memcpy(writeTo, readFrom, n); writeTo += n; - memcpy(writeTo, _replace.buffer, _replace.len); - writeTo += _replace.len; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; readFrom = foundAt + find.len; len += diff; } @@ -697,7 +732,7 @@ void String::replace(const String& find, const String& _replace) memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); len += diff; buffer[len] = 0; - memcpy(buffer + index, _replace.buffer, _replace.len); + memcpy(buffer + index, replace.buffer, replace.len); index--; } } diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h index cd90253c..75a3e143 100644 --- a/cores/arduino/WString.h +++ b/cores/arduino/WString.h @@ -63,7 +63,8 @@ class String // be false). String(const char *cstr = ""); String(const String &str); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String(const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) String(String &&rval); String(StringSumHelper &&rval); #endif @@ -91,7 +92,8 @@ class String // marked as invalid ("if (s)" will be false). String & operator = (const String &rhs); String & operator = (const char *cstr); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String & operator = (const __FlashStringHelper *str); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) String & operator = (String &&rval); String & operator = (StringSumHelper &&rval); #endif @@ -113,6 +115,7 @@ class String unsigned char concat(unsigned long long num); unsigned char concat(float num); unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper * str); // if there's not enough memory for the concatenated value, the string // will be left unchanged (but this isn't signalled in any way) @@ -128,6 +131,7 @@ class String String & operator += (unsigned long long num) {concat(num); return (*this);} String & operator += (float num) {concat(num); return (*this);} String & operator += (double num) {concat(num); return (*this);} + String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); @@ -141,6 +145,7 @@ class String friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long long num); friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); + friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); // comparison (only works w/ Strings and "strings") operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } @@ -196,11 +201,11 @@ class String float toFloat(void) const; char * getCSpec(int base, bool issigned, bool islong); +protected: char *buffer; // the actual char array unsigned int capacity; // the array length minus one (for the '\0') unsigned int len; // the String length (not counting the '\0') - unsigned char flags; // unused, for future features - +protected: void init(void); void invalidate(void); unsigned char changeBuffer(unsigned int maxStrLen); @@ -208,7 +213,8 @@ class String // copy and move String & copy(const char *cstr, unsigned int length); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ + String & copy(const __FlashStringHelper *pstr, unsigned int length); + #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) void move(String &rhs); #endif }; From f07a20aa02e5421b1fc6e9775fdeb2221c8bd2a7 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 28 Oct 2015 12:50:35 +0100 Subject: [PATCH 3/4] remove misleading SERIAL_PORT_USBVIRTUAL define the Serial via USB port is not a real virtual cdc port (it still emulates an Hardware Serial), remove to avoid sketches getting confused and expect CDC flow control functions --- variants/arduino_101/variant.h | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/arduino_101/variant.h b/variants/arduino_101/variant.h index c19930d1..936649af 100644 --- a/variants/arduino_101/variant.h +++ b/variants/arduino_101/variant.h @@ -197,7 +197,6 @@ void CDCSerial_bytes_sent(uint32_t num); // SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX // pins are NOT connected to anything by default. #define SERIAL_PORT_MONITOR Serial -#define SERIAL_PORT_USBVIRTUAL SerialUSB #define SERIAL_PORT_HARDWARE_OPEN Serial1 #define SERIAL_PORT_HARDWARE Serial1 #define SERIAL_PORT_HARDWARE1 Serial1 From 6f35dfd332c30b135c14d1f718f923299d7e6695 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 28 Oct 2015 12:53:47 +0100 Subject: [PATCH 4/4] stdlib_noniso: expand all functions up to base 36 needed to pass a very strict test Porting of latest Due implementation --- cores/arduino/WString.cpp | 3 +- cores/arduino/stdlib_noniso.cpp | 148 ++++++++++++++++---------------- 2 files changed, 77 insertions(+), 74 deletions(-) diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index a604d2a7..2f748fb8 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -29,8 +29,7 @@ #include "WString.h" #include - - +#include "stdlib_noniso.h" /*********************************************/ /* Constructors */ diff --git a/cores/arduino/stdlib_noniso.cpp b/cores/arduino/stdlib_noniso.cpp index 2238b007..e583b691 100644 --- a/cores/arduino/stdlib_noniso.cpp +++ b/cores/arduino/stdlib_noniso.cpp @@ -50,96 +50,101 @@ void reverse(char* begin, char* end) { } } -char* itoa(int value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } - - char* out = result; - int quotient = abs(value); +char* itoa( int val, char *string, int radix ) +{ + return ltoa( val, string, radix ) ; +} - do { - const int tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); +char* ltoa( long val, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; - // Apply negative sign - if(value < 0) - *out++ = '-'; + if ( string == NULL ) + { + return 0 ; + } - reverse(result, out); - *out = 0; - return result; -} + if (radix > 36 || radix <= 1) + { + return 0 ; + } -char* ltoa(long value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; + sign = (radix == 10 && val < 0); + if (sign) + { + v = -val; + } + else + { + v = (unsigned long)val; } - char* out = result; - long quotient = abs(value); + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } - do { - const long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + sp = string; - // Apply negative sign - if(value < 0) - *out++ = '-'; + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; - reverse(result, out); - *out = 0; - return result; + return string; } -char* utoa(unsigned value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; - } +char* utoa( unsigned int val, char *string, int radix ) +{ + return ultoa( val, string, radix ) ; +} - char* out = result; - unsigned quotient = value; +char* ultoa( unsigned long val, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = val; + char *sp; - do { - const unsigned tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + if ( string == NULL ) + { + return 0; + } - reverse(result, out); - *out = 0; - return result; -} + if (radix > 36 || radix <= 1) + { + return 0; + } -char* ultoa(unsigned long value, char* result, int base) { - if(base < 2 || base > 16) { - *result = 0; - return result; + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; } - char* out = result; - unsigned long quotient = value; + sp = string; - do { - const unsigned long tmp = quotient / base; - *out = "0123456789abcdef"[quotient - (tmp * base)]; - ++out; - quotient = tmp; - } while(quotient); + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; - reverse(result, out); - *out = 0; - return result; + return string; } char * dtostrf(double number, signed char width, unsigned char prec, char *s) { @@ -190,7 +195,6 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) { *out = '.'; ++out; - for (unsigned char decShift = prec; decShift > 0; decShift--) { remainder *= 10.0; }