diff --git a/README.md b/README.md index 506569a8..e533b69e 100644 --- a/README.md +++ b/README.md @@ -85,9 +85,9 @@ Documentation for how to integrate with a Arduino core (which is necessary if yo * [ArduinoCore-mbed](https://github.com/arduino/ArduinoCore-mbed#clone-the-repository-in-sketchbookhardwarearduino-git) * [ArduinoCore-samd](https://github.com/arduino/ArduinoCore-samd/#developing) -## Donations +## Support the project -This open source code is maintained by Arduino with the help of the community. We invest a considerable amount of time in testing code, optimizing it and introducing new features. Please consider [donating](https://www.arduino.cc/en/donate/) or [sponsoring](https://github.com/sponsors/arduino) to support our work, as well as [buying original Arduino boards](https://store.arduino.cc) which is the best way to make sure our effort can continue in the long term. +This open source code is maintained by Arduino with the help of the community. We invest a considerable amount of time in testing code, optimizing it and introducing new features. Please consider [buying original Arduino boards](https://store.arduino.cc) to support our work on the project. ## License and credits diff --git a/api/ArduinoAPI.h b/api/ArduinoAPI.h index 3d53085b..a7d8c0b8 100644 --- a/api/ArduinoAPI.h +++ b/api/ArduinoAPI.h @@ -20,8 +20,8 @@ #ifndef ARDUINO_API_H #define ARDUINO_API_H -// version 1.5.1 -#define ARDUINO_API_VERSION 10501 +// version 1.5.2 +#define ARDUINO_API_VERSION 10502 #include "Binary.h" diff --git a/api/Common.h b/api/Common.h index 5afdf945..9b28f40a 100644 --- a/api/Common.h +++ b/api/Common.h @@ -41,11 +41,6 @@ typedef enum { INPUT_PULLUP = 0x2, INPUT_PULLDOWN = 0x3, OUTPUT_OPENDRAIN = 0x4, - - OUTPUT_2MA = 0x5, - OUTPUT_4MA = 0x6, - OUTPUT_8MA = 0x7, - OUTPUT_12MA = 0x8, } PinMode; typedef enum { diff --git a/api/HardwareSPI.h b/api/HardwareSPI.h index 58f5d75c..7ce833ca 100644 --- a/api/HardwareSPI.h +++ b/api/HardwareSPI.h @@ -34,33 +34,42 @@ typedef enum { SPI_MODE3 = 3, } SPIMode; +// Platforms should define SPI_HAS_PERIPHERAL_MODE if SPI peripheral +// mode is supported, to allow applications to check whether peripheral +// mode is available or not. +typedef enum { + SPI_CONTROLLER = 0, + SPI_PERIPHERAL = 1, +} SPIBusMode; + class SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) { + SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, SPIBusMode busMode = SPI_CONTROLLER) { if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, dataMode); + init_AlwaysInline(clock, bitOrder, dataMode, busMode); } else { - init_MightInline(clock, bitOrder, dataMode); + init_MightInline(clock, bitOrder, dataMode, busMode); } } - SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode) { + SPISettings(uint32_t clock, BitOrder bitOrder, int dataMode, SPIBusMode busMode = SPI_CONTROLLER) { if (__builtin_constant_p(clock)) { - init_AlwaysInline(clock, bitOrder, (SPIMode)dataMode); + init_AlwaysInline(clock, bitOrder, static_cast(dataMode), busMode); } else { - init_MightInline(clock, bitOrder, (SPIMode)dataMode); + init_MightInline(clock, bitOrder, static_cast(dataMode), busMode); } } // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. - SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } + SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, SPI_CONTROLLER); } bool operator==(const SPISettings& rhs) const { if ((this->clockFreq == rhs.clockFreq) && (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode)) { + (this->dataMode == rhs.dataMode) && + (this->busMode == rhs.busMode)) { return true; } return false; @@ -80,22 +89,27 @@ class SPISettings { BitOrder getBitOrder() const { return (bitOrder); } + SPIBusMode getBusMode() const { + return busMode; + } private: - void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) { - init_AlwaysInline(clock, bitOrder, dataMode); + void init_MightInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, SPIBusMode busMode) { + init_AlwaysInline(clock, bitOrder, dataMode, busMode); } // Core developer MUST use an helper function in beginTransaction() to use this data - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) __attribute__((__always_inline__)) { + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, SPIBusMode busMode) __attribute__((__always_inline__)) { this->clockFreq = clock; this->dataMode = dataMode; this->bitOrder = bitOrder; + this->busMode = busMode; } uint32_t clockFreq; SPIMode dataMode; BitOrder bitOrder; + SPIBusMode busMode; friend class HardwareSPI; }; @@ -111,9 +125,6 @@ class HardwareSPI virtual uint16_t transfer16(uint16_t data) = 0; virtual void transfer(void *buf, size_t count) = 0; - // EFP3 - Additional block-based versions we implement - virtual void transfer(const void *txbuf, void *rxbuf, size_t count) = 0; - // Transaction Functions virtual void usingInterrupt(int interruptNumber) = 0; virtual void notUsingInterrupt(int interruptNumber) = 0; diff --git a/api/HardwareSerial.h b/api/HardwareSerial.h index f5f9d64f..b687cdf1 100644 --- a/api/HardwareSerial.h +++ b/api/HardwareSerial.h @@ -103,6 +103,4 @@ class HardwareSerial : public Stream // XXX: Are we keeping the serialEvent API? extern void serialEventRun(void) __attribute__((weak)); -} - -using arduino::HardwareSerial; +} \ No newline at end of file diff --git a/api/IPAddress.cpp b/api/IPAddress.cpp index 404b6562..05b41bc1 100644 --- a/api/IPAddress.cpp +++ b/api/IPAddress.cpp @@ -1,83 +1,147 @@ /* - IPAddress.cpp - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. + IPAddress.cpp - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. 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 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. + 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 - */ + 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 -#include +#include "IPAddress.h" +#include "Print.h" -IPAddress::IPAddress(const IPAddress& from) +using namespace arduino; + +IPAddress::IPAddress() : IPAddress(IPv4) {} + +IPAddress::IPAddress(IPType ip_type) +{ + _type = ip_type; + memset(_address.bytes, 0, sizeof(_address.bytes)); +} + +IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) +{ + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + _address.bytes[IPADDRESS_V4_BYTES_INDEX] = first_octet; + _address.bytes[IPADDRESS_V4_BYTES_INDEX + 1] = second_octet; + _address.bytes[IPADDRESS_V4_BYTES_INDEX + 2] = third_octet; + _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = fourth_octet; +} + +IPAddress::IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16) { + _type = IPv6; + _address.bytes[0] = o1; + _address.bytes[1] = o2; + _address.bytes[2] = o3; + _address.bytes[3] = o4; + _address.bytes[4] = o5; + _address.bytes[5] = o6; + _address.bytes[6] = o7; + _address.bytes[7] = o8; + _address.bytes[8] = o9; + _address.bytes[9] = o10; + _address.bytes[10] = o11; + _address.bytes[11] = o12; + _address.bytes[12] = o13; + _address.bytes[13] = o14; + _address.bytes[14] = o15; + _address.bytes[15] = o16; +} + +IPAddress::IPAddress(uint32_t address) { - ip_addr_copy(_ip, from._ip); + // IPv4 only + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + _address.dword[IPADDRESS_V4_DWORD_INDEX] = address; + + // NOTE on conversion/comparison and uint32_t: + // These conversions are host platform dependent. + // There is a defined integer representation of IPv4 addresses, + // based on network byte order (will be the value on big endian systems), + // e.g. http://2398766798 is the same as http://142.250.70.206, + // However on little endian systems the octets 0x83, 0xFA, 0x46, 0xCE, + // in that order, will form the integer (uint32_t) 3460758158 . } -IPAddress::IPAddress() { - _ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address +IPAddress::IPAddress(const uint8_t *address) : IPAddress(IPv4, address) {} + +IPAddress::IPAddress(IPType ip_type, const uint8_t *address) +{ + _type = ip_type; + if (ip_type == IPv4) { + memset(_address.bytes, 0, sizeof(_address.bytes)); + memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t)); + } else { + memcpy(_address.bytes, address, sizeof(_address.bytes)); + } } -bool IPAddress::isSet () const { - return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE); +IPAddress::IPAddress(const char *address) +{ + fromString(address); } -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { - setV4(); - (*this)[0] = first_octet; - (*this)[1] = second_octet; - (*this)[2] = third_octet; - (*this)[3] = fourth_octet; +String IPAddress::toString4() const +{ + char szRet[16]; + snprintf(szRet, sizeof(szRet), "%u.%u.%u.%u", _address.bytes[IPADDRESS_V4_BYTES_INDEX], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 1], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 2], _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3]); + return String(szRet); } -void IPAddress::ctor32(uint32_t address) { - setV4(); - v4() = address; +String IPAddress::toString6() const +{ + char szRet[40]; + snprintf(szRet, sizeof(szRet), "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + _address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3], + _address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7], + _address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11], + _address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]); + return String(szRet); } -IPAddress::IPAddress(const uint8_t *address) { - setV4(); - (*this)[0] = address[0]; - (*this)[1] = address[1]; - (*this)[2] = address[2]; - (*this)[3] = address[3]; +String IPAddress::toString() const +{ + if (_type == IPv4) { + return toString4(); + } else { + return toString6(); + } } bool IPAddress::fromString(const char *address) { if (!fromString4(address)) { -#if LWIP_IPV6 return fromString6(address); -#else - return false; -#endif } return true; } -bool IPAddress::fromString4(const char *address) { - // TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats +bool IPAddress::fromString4(const char *address) +{ + // TODO: add support for "a", "a.b", "a.b.c" formats - uint16_t acc = 0; // Accumulator + int16_t acc = -1; // Accumulator uint8_t dots = 0; + memset(_address.bytes, 0, sizeof(_address.bytes)); while (*address) { char c = *address++; if (c >= '0' && c <= '9') { - acc = acc * 10 + (c - '0'); + acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0'); if (acc > 255) { // Value out of [0..255] range return false; @@ -86,11 +150,15 @@ bool IPAddress::fromString4(const char *address) { else if (c == '.') { if (dots == 3) { - // Too much dots (there must be 3 dots) + // Too many dots (there must be 3 dots) return false; } - (*this)[dots++] = acc; - acc = 0; + if (acc < 0) { + /* No value between dots, e.g. '1..' */ + return false; + } + _address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc; + acc = -1; } else { @@ -103,105 +171,23 @@ bool IPAddress::fromString4(const char *address) { // Too few dots (there must be 3 dots) return false; } - (*this)[3] = acc; - - setV4(); - return true; -} - -IPAddress& IPAddress::operator=(const uint8_t *address) { - setV4(); - v4() = *reinterpret_cast(address); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) { - setV4(); - v4() = address; - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) const { - return isV4() && v4() == *reinterpret_cast(addr); -} - -size_t IPAddress::printTo(Print& p) const { - String s = toString(); - return p.print(s); -} - -String IPAddress::toString() const -{ - String s; - - if (!isSet()) - return "(IP unset)"; - -#if LWIP_IPV6 - if (isV6()) { - int count0 = 0; - for (int i = 0; i < 8; i++) { - uint16_t bit = PP_NTOHS(raw6()[i]); - if (bit || count0 < 0) { - char buff[64]; - snprintf(buff, 64, "%x", bit); - buff[63] = 0; - s += buff; - if (count0 > 0) - // no more hiding 0 - count0 = -8; - } else - count0++; - if ((i != 7 && count0 < 2) || count0 == 7) - s += ':'; - } - return s; - } -#endif - - for(int i = 0; i < 4; i++) { - char buff[16]; - snprintf(buff, 16, "%d", (*this)[i]); - buff[15] = 0; - s += buff; - if (i != 3) - s += '.'; + if (acc < 0) { + /* No value between dots, e.g. '1..' */ + return false; } - return s; - -} - -bool IPAddress::isValid(const String& arg) { - return IPAddress().fromString(arg); -} - -bool IPAddress::isValid(const char* arg) { - return IPAddress().fromString(arg); -} - -namespace arduino { -const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6 -const IPAddress INADDR_NONE(255,255,255,255); -}; - -void IPAddress::clear() { - (*this) = INADDR_ANY; + _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc; + _type = IPv4; + return true; } -/**************************************/ - -#if LWIP_IPV6 - bool IPAddress::fromString6(const char *address) { - // TODO: test test test - uint32_t acc = 0; // Accumulator - int dots = 0, doubledots = -1; + int colons = 0, double_colons = -1; while (*address) { char c = tolower(*address++); - if (isalnum(c)) { + if (isalnum(c) && c <= 'f') { if (c >= 'a') c -= 'a' - '0' - 10; acc = acc * 16 + (c - '0'); @@ -211,17 +197,27 @@ bool IPAddress::fromString6(const char *address) { } else if (c == ':') { if (*address == ':') { - if (doubledots >= 0) + if (double_colons >= 0) { // :: allowed once return false; + } + if (*address != '\0' && *(address + 1) == ':') { + // ::: not allowed + return false; + } // remember location - doubledots = dots + !!acc; + double_colons = colons + !!acc; address++; + } else if (*address == '\0') { + // can't end with a single colon + return false; } - if (dots == 7) + if (colons == 7) // too many separators return false; - raw6()[dots++] = PP_HTONS(acc); + _address.bytes[colons * 2] = acc >> 8; + _address.bytes[colons * 2 + 1] = acc & 0xff; + colons++; acc = 0; } else @@ -229,20 +225,144 @@ bool IPAddress::fromString6(const char *address) { return false; } - if (doubledots == -1 && dots != 7) + if (double_colons == -1 && colons != 7) { // Too few separators return false; - raw6()[dots++] = PP_HTONS(acc); - - if (doubledots != -1) { - for (int i = dots - doubledots - 1; i >= 0; i--) - raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i]; - for (int i = doubledots; i < 8 - dots + doubledots; i++) - raw6()[i] = 0; + } + if (double_colons > -1 && colons > 6) { + // Too many segments (double colon must be at least one zero field) + return false; + } + _address.bytes[colons * 2] = acc >> 8; + _address.bytes[colons * 2 + 1] = acc & 0xff; + colons++; + + if (double_colons != -1) { + for (int i = colons * 2 - double_colons * 2 - 1; i >= 0; i--) + _address.bytes[16 - colons * 2 + double_colons * 2 + i] = _address.bytes[double_colons * 2 + i]; + for (int i = double_colons * 2; i < 16 - colons * 2 + double_colons * 2; i++) + _address.bytes[i] = 0; } - setV6(); + _type = IPv6; return true; } -#endif +IPAddress& IPAddress::operator=(const uint8_t *address) +{ + // IPv4 only conversion from byte pointer + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + memcpy(&_address.bytes[IPADDRESS_V4_BYTES_INDEX], address, sizeof(uint32_t)); + return *this; +} + +IPAddress& IPAddress::operator=(const char *address) +{ + fromString(address); + return *this; +} + +IPAddress& IPAddress::operator=(uint32_t address) +{ + // IPv4 conversion + // See note on conversion/comparison and uint32_t + _type = IPv4; + memset(_address.bytes, 0, sizeof(_address.bytes)); + _address.dword[IPADDRESS_V4_DWORD_INDEX] = address; + return *this; +} + +bool IPAddress::operator==(const IPAddress& addr) const { + return (addr._type == _type) + && (memcmp(addr._address.bytes, _address.bytes, sizeof(_address.bytes)) == 0); +} + +bool IPAddress::operator==(const uint8_t* addr) const +{ + // IPv4 only comparison to byte pointer + // Can't support IPv6 as we know our type, but not the length of the pointer + return _type == IPv4 && memcmp(addr, &_address.bytes[IPADDRESS_V4_BYTES_INDEX], sizeof(uint32_t)) == 0; +} + +uint8_t IPAddress::operator[](int index) const { + if (_type == IPv4) { + return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; + } + return _address.bytes[index]; +} + +uint8_t& IPAddress::operator[](int index) { + if (_type == IPv4) { + return _address.bytes[IPADDRESS_V4_BYTES_INDEX + index]; + } + return _address.bytes[index]; +} + +size_t IPAddress::printTo(Print& p) const +{ + size_t n = 0; + + if (_type == IPv6) { + // IPv6 IETF canonical format: compress left-most longest run of two or more zero fields, lower case + int8_t longest_start = -1; + int8_t longest_length = 1; + int8_t current_start = -1; + int8_t current_length = 0; + for (int8_t f = 0; f < 8; f++) { + if (_address.bytes[f * 2] == 0 && _address.bytes[f * 2 + 1] == 0) { + if (current_start == -1) { + current_start = f; + current_length = 1; + } else { + current_length++; + } + if (current_length > longest_length) { + longest_start = current_start; + longest_length = current_length; + } + } else { + current_start = -1; + } + } + for (int f = 0; f < 8; f++) { + if (f < longest_start || f >= longest_start + longest_length) { + uint8_t c1 = _address.bytes[f * 2] >> 4; + uint8_t c2 = _address.bytes[f * 2] & 0xf; + uint8_t c3 = _address.bytes[f * 2 + 1] >> 4; + uint8_t c4 = _address.bytes[f * 2 + 1] & 0xf; + if (c1 > 0) { + n += p.print((char)(c1 < 10 ? '0' + c1 : 'a' + c1 - 10)); + } + if (c1 > 0 || c2 > 0) { + n += p.print((char)(c2 < 10 ? '0' + c2 : 'a' + c2 - 10)); + } + if (c1 > 0 || c2 > 0 || c3 > 0) { + n += p.print((char)(c3 < 10 ? '0' + c3 : 'a' + c3 - 10)); + } + n += p.print((char)(c4 < 10 ? '0' + c4 : 'a' + c4 - 10)); + if (f < 7) { + n += p.print(':'); + } + } else if (f == longest_start) { + if (longest_start == 0) { + n += p.print(':'); + } + n += p.print(':'); + } + } + return n; + } + + // IPv4 + for (int i =0; i < 3; i++) + { + n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[IPADDRESS_V4_BYTES_INDEX + 3], DEC); + return n; +} + +const IPAddress arduino::IN6ADDR_ANY(IPv6); +const IPAddress arduino::INADDR_NONE(0,0,0,0); diff --git a/api/IPAddress.h b/api/IPAddress.h index a395c29b..31a2d06d 100644 --- a/api/IPAddress.h +++ b/api/IPAddress.h @@ -1,236 +1,122 @@ /* - IPAddress.h - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. All right reserved. + IPAddress.h - Base class that provides IPAddress + Copyright (c) 2011 Adrian McEwen. 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 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. + 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 - */ + 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 +*/ #pragma once #include -#include -#include - -#include -#include -#include +#include "Printable.h" +#include "String.h" +#define IPADDRESS_V4_BYTES_INDEX 12 +#define IPADDRESS_V4_DWORD_INDEX 3 // forward declarations of global name space friend classes class EthernetClass; class DhcpClass; class DNSClient; - namespace arduino { -// to display a netif id with printf: -#define NETIFID_STR "%c%c%u" -#define NETIFID_VAL(netif) \ - ((netif)? (netif)->name[0]: '-'), \ - ((netif)? (netif)->name[1]: '-'), \ - ((netif)? netif_get_index(netif): 42) - // A class to make it easier to handle and pass around IP addresses -// IPv6 update: -// IPAddress is now a decorator class for lwIP's ip_addr_t -// fully backward compatible with legacy IPv4-only Arduino's -// with unchanged footprint when IPv6 is disabled - -class IPAddress: public Printable { - private: -#if !LWIP_IPV6 - // Ugly hack to allow Arduino Ethernet library to twiddle internal bits. - // This can only work in IPv4-only mode, of course. - union { - ip_addr_t _ip; - struct { - uint8_t bytes[4]; - } _address; - }; - static_assert(sizeof(_ip) == sizeof(_address), "IP_ADDR_T size != _ADDRESS size"); -#else - ip_addr_t _ip; -#endif - - // Access the raw byte array containing the address. Because this returns a pointer - // to the internal structure rather than a copy of the address this function should only - // be used when you know that the usage of the returned uint8_t* will be transient and not - // stored. - uint8_t* raw_address() { - return reinterpret_cast(&v4()); - } - const uint8_t* raw_address() const { - return reinterpret_cast(&v4()); - } - - void ctor32 (uint32_t); - - public: - // Constructors - IPAddress(); - IPAddress(const IPAddress& from); - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint32_t address) { ctor32(address); } -// IPAddress(unsigned long address) { ctor32(address); } - IPAddress(int address) { ctor32(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 isV4()? v4(): (uint32_t)0; } - operator uint32_t() { return isV4()? v4(): (uint32_t)0; } - - bool isSet () const; - operator bool () const { return isSet(); } // <- - operator bool () { return isSet(); } // <- both are needed - - // generic IPv4 wrapper to uint32-view like arduino loves to see it - const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const) - uint32_t& v4() { return ip_2_ip4(&_ip)->addr; } - - bool operator==(const IPAddress& addr) const { - return ip_addr_cmp(&_ip, &addr._ip); - } - bool operator!=(const IPAddress& addr) const { - return !ip_addr_cmp(&_ip, &addr._ip); - } - bool operator==(uint32_t addr) const { - return isV4() && v4() == addr; - } -// bool operator==(unsigned long addr) const { -// return isV4() && v4() == (uint32_t)addr; -// } - bool operator!=(uint32_t addr) const { - return !(isV4() && v4() == addr); - } -// bool operator!=(unsigned long addr) const { -// return isV4() && v4() != (uint32_t)addr; -// } - bool operator==(const uint8_t* addr) const; - - int operator>>(int n) const { - return isV4()? v4() >> n: 0; - } - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { - return isV4()? *(raw_address() + index): 0; - } - uint8_t& operator[](int index) { - setV4(); - return *(raw_address() + index); - } - - // Overloaded copy operators to allow initialisation of IPAddress objects from other types - IPAddress& operator=(const uint8_t *address); - IPAddress& operator=(uint32_t address); - IPAddress& operator=(const IPAddress&) = default; - - virtual size_t printTo(Print& p) const; - String toString() const; - - void clear(); - - /* - check if input string(arg) is a valid IPV4 address or not. - return true on valid. - return false on invalid. - */ - static bool isValid(const String& arg); - static bool isValid(const char* arg); - - friend class WiFiClass; - friend class EthernetClass; - friend class UDP; - friend class Client; - friend class Server; - friend class DhcpClass; - friend class DNSClient; - - friend ::EthernetClass; - friend ::DhcpClass; - friend ::DNSClient; - - /* - lwIP address compatibility - */ - //IPAddress(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; } - //IPAddress(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; } - - //IPAddress& operator=(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; return *this; } - //IPAddress& operator=(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; return *this; } - - operator ip_addr_t () const { return _ip; } - operator const ip_addr_t*() const { return &_ip; } - operator ip_addr_t*() { return &_ip; } - - bool isV4() const { return IP_IS_V4_VAL(_ip); } - void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); } - - bool isLocal () const { return ip_addr_islinklocal(&_ip); } - - - IPAddress(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); } - IPAddress(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); } - - IPAddress& operator=(const ip_addr_t& lwip_addr) { ip_addr_copy(_ip, lwip_addr); return *this; } - IPAddress& operator=(const ip_addr_t* lwip_addr) { ip_addr_copy(_ip, *lwip_addr); return *this; } - -#if LWIP_IPV6 - uint16_t* raw6() - { - setV6(); - return reinterpret_cast(ip_2_ip6(&_ip)); - } - - const uint16_t* raw6() const - { - return isV6()? reinterpret_cast(ip_2_ip6(&_ip)): nullptr; - } - - // when not IPv6, ip_addr_t == ip4_addr_t so this one would be ambiguous - // required otherwise - operator const ip4_addr_t*() const { return isV4()? ip_2_ip4(&_ip): nullptr; } - - bool isV6() const { return IP_IS_V6_VAL(_ip); } - void setV6() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V6); } - - protected: - bool fromString6(const char *address); - -#else - - // allow portable code when IPv6 is not enabled - - uint16_t* raw6() { return nullptr; } - const uint16_t* raw6() const { return nullptr; } - bool isV6() const { return false; } - void setV6() { } -#endif - - protected: - bool fromString4(const char *address); +enum IPType { + IPv4, + IPv6 +}; +class IPAddress : public Printable { +private: + union { + uint8_t bytes[16]; + uint32_t dword[4]; + } _address; + IPType _type; + + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _type == IPv4 ? &_address.bytes[IPADDRESS_V4_BYTES_INDEX] : _address.bytes; } + +public: + // Constructors + + // Default IPv4 + IPAddress(); + IPAddress(IPType ip_type); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint8_t o1, uint8_t o2, uint8_t o3, uint8_t o4, uint8_t o5, uint8_t o6, uint8_t o7, uint8_t o8, uint8_t o9, uint8_t o10, uint8_t o11, uint8_t o12, uint8_t o13, uint8_t o14, uint8_t o15, uint8_t o16); + // IPv4; see implementation note + IPAddress(uint32_t address); + // Default IPv4 + IPAddress(const uint8_t *address); + IPAddress(IPType ip_type, const uint8_t *address); + // If IPv4 fails tries IPv6 see fromString function + IPAddress(const char *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 uint32_t is expected + // NOTE: IPv4 only; see implementation note + operator uint32_t() const { return _type == IPv4 ? _address.dword[IPADDRESS_V4_DWORD_INDEX] : 0; }; + + bool operator==(const IPAddress& addr) const; + bool operator!=(const IPAddress& addr) const { return !(*this == addr); }; + + // NOTE: IPv4 only; we don't know the length of the pointer + bool operator==(const uint8_t* addr) const; + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const; + uint8_t& operator[](int index); + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + // NOTE: IPv4 only + IPAddress& operator=(const uint8_t *address); + // NOTE: IPv4 only; see implementation note + IPAddress& operator=(uint32_t address); + // If IPv4 fails tries IPv6 see fromString function + IPAddress& operator=(const char *address); + + virtual size_t printTo(Print& p) const; + String toString() const; + + IPType type() const { return _type; } + + friend class UDP; + friend class Client; + friend class Server; + + friend ::EthernetClass; + friend ::DhcpClass; + friend ::DNSClient; + +protected: + bool fromString4(const char *address); + bool fromString6(const char *address); + String toString4() const; + String toString6() const; }; -extern const IPAddress INADDR_ANY; +extern const IPAddress IN6ADDR_ANY; extern const IPAddress INADDR_NONE; - } + +using arduino::IPAddress; \ No newline at end of file diff --git a/api/Interrupts.h b/api/Interrupts.h index c3e37ade..b397eb7d 100644 --- a/api/Interrupts.h +++ b/api/Interrupts.h @@ -47,15 +47,19 @@ template void attachInterrupt(pin_size_t interruptNum, voidTemplateF // TODO: add structure to delete(__container__) when detachInterrupt() is called auto f = [](void* a) -> void { - T param = *(T*)((struct __container__*)a)->param; - (((struct __container__*)a)->function)(param); + T param = *(static_cast((static_cast*>(a))->param)); + //T param = *(T*) ((struct __container__*)a)->param; + (static_cast*>)(a)->function(param); + + //(((struct __container__*)a)->function)(param); }; attachInterruptParam(interruptNum, f, mode, cont); } template void attachInterrupt(pin_size_t interruptNum, voidTemplateFuncPtrParam userFunc, PinStatus mode, T* param) { - attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param); + //attachInterruptParam(interruptNum, (voidFuncPtrParam)userFunc, mode, (void*)param); + attachInterruptParam(interruptNum, static_cast(userFunc), mode, static_cast(param)) } } diff --git a/api/PluggableUSB.cpp b/api/PluggableUSB.cpp index ca19d65d..977b4df4 100644 --- a/api/PluggableUSB.cpp +++ b/api/PluggableUSB.cpp @@ -87,7 +87,9 @@ bool PluggableUSB_::plug(PluggableUSBModule *node) node->pluggedEndpoint = lastEp; lastIf += node->numInterfaces; for (uint8_t i = 0; i < node->numEndpoints; i++) { - *(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i]; + *(static_cast(epBuffer(lastEp))) = node->endpointType[i]; + + //*(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i]; lastEp++; } return true; diff --git a/api/Print.cpp b/api/Print.cpp index f9f2ab8b..603fc468 100644 --- a/api/Print.cpp +++ b/api/Print.cpp @@ -17,7 +17,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include @@ -74,17 +73,17 @@ size_t Print::print(char c) size_t Print::print(unsigned char b, int base) { - return print((unsigned long) b, base); + return print(static_cast(b), base); } size_t Print::print(int n, int base) { - return print((long) n, base); + return print(static_cast(n), base); } size_t Print::print(unsigned int n, int base) { - return print((unsigned long) n, base); + return print(static_cast(n), base); } size_t Print::print(long n, int base) @@ -237,53 +236,6 @@ size_t Print::println(const Printable& x) return n; } -size_t Print::printf(const char *format, ...) { - va_list arg; - va_start(arg, format); - char temp[64]; - char* buffer = temp; - size_t len = vsnprintf(temp, sizeof(temp), format, arg); - va_end(arg); - if (len > sizeof(temp) - 1) { - buffer = new char[len + 1]; - if (!buffer) { - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - len = write((const uint8_t*) buffer, len); - if (buffer != temp) { - delete[] buffer; - } - return len; -} - -// TODO - must be better way than cut-n-paste! -size_t Print::printf_P(const char *format, ...) { - va_list arg; - va_start(arg, format); - char temp[64]; - char* buffer = temp; - size_t len = vsnprintf(temp, sizeof(temp), format, arg); - va_end(arg); - if (len > sizeof(temp) - 1) { - buffer = new char[len + 1]; - if (!buffer) { - return 0; - } - va_start(arg, format); - vsnprintf(buffer, len + 1, format, arg); - va_end(arg); - } - len = write((const uint8_t*) buffer, len); - if (buffer != temp) { - delete[] buffer; - } - return len; -} - // Private Methods ///////////////////////////////////////////////////////////// size_t Print::printNumber(unsigned long n, uint8_t base) @@ -414,8 +366,8 @@ size_t Print::printFloat(double number, int digits) number += rounding; // Extract the integer part of the number and print it - unsigned long int_part = (unsigned long)number; - double remainder = number - (double)int_part; + unsigned long int_part = static_cast(number); + double remainder = number - static_cast(int_part); n += print(int_part); // Print the decimal point, but only if there are digits beyond @@ -427,7 +379,7 @@ size_t Print::printFloat(double number, int digits) while (digits-- > 0) { remainder *= 10.0; - unsigned int toPrint = (unsigned int)remainder; + unsigned int toPrint = static_cast(remainder); n += print(toPrint); remainder -= toPrint; } diff --git a/api/Print.h b/api/Print.h index 149bf010..89e857ed 100644 --- a/api/Print.h +++ b/api/Print.h @@ -50,11 +50,11 @@ class Print virtual size_t write(uint8_t) = 0; size_t write(const char *str) { if (str == NULL) return 0; - return write((const uint8_t *)str, strlen(str)); + return write(reinterpret_cast(str), strlen(str)); } virtual size_t write(const uint8_t *buffer, size_t size); size_t write(const char *buffer, size_t size) { - return write((const uint8_t *)buffer, size); + return write(reinterpret_cast(buffer), size); } // default to zero, meaning "a single write may block" @@ -90,12 +90,8 @@ class Print size_t println(const Printable&); size_t println(void); - // EFP3 - Add printf() to make life so much easier... - size_t printf(const char *format, ...); - size_t printf_P(const char *format, ...); - virtual void flush() { /* Empty implementation for backward compatibility */ } }; } -using arduino::Print; +using arduino::Print; \ No newline at end of file diff --git a/api/RingBuffer.h b/api/RingBuffer.h index b69c20d4..b1ad1cae 100644 --- a/api/RingBuffer.h +++ b/api/RingBuffer.h @@ -127,7 +127,7 @@ int RingBufferN::peek() template int RingBufferN::nextIndex(int index) { - return (uint32_t)(index + 1) % N; + return static_cast(index + 1) % N; } template diff --git a/api/Stream.h b/api/Stream.h index e81c71ba..10b42852 100644 --- a/api/Stream.h +++ b/api/Stream.h @@ -69,20 +69,20 @@ class Stream : public Print unsigned long getTimeout(void) { return _timeout; } bool find(const char *target); // reads data from the stream until the target string is found - bool find(const uint8_t *target) { return find ((const char *)target); } + bool find(const uint8_t *target) { return find (reinterpret_cast(target)); } // returns true if target string is found, false if timed out (see setTimeout) bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(const uint8_t *target, size_t length) { return find ((const char *)target, length); } + bool find(const uint8_t *target, size_t length) { return find (reinterpret_cast(target), length); } // returns true if target string is found, false if timed out bool find(char target) { return find (&target, 1); } bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found - bool findUntil(const uint8_t *target, const char *terminator) { return findUntil((const char *)target, terminator); } + bool findUntil(const uint8_t *target, const char *terminator) { return findUntil(reinterpret_cast(target), terminator); } bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil((const char *)target, targetLen, terminate, termLen); } + bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) {return findUntil(reinterpret_cast(target), targetLen, terminate, termLen); } long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // returns the first valid (long) integer value from the current position. @@ -95,12 +95,12 @@ class Stream : public Print // float version of parseInt size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + size_t readBytes( uint8_t *buffer, size_t length) { return readBytes(reinterpret_cast(buffer), length); } // terminates if length characters have been read or timeout (see setTimeout) // returns the number of characters placed in the buffer (0 means no valid data found) size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, reinterpret_cast(buffer), length); } // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) diff --git a/api/String.cpp b/api/String.cpp index 4f176374..8b995cfa 100644 --- a/api/String.cpp +++ b/api/String.cpp @@ -175,7 +175,7 @@ bool String::reserve(unsigned int size) bool String::changeBuffer(unsigned int maxStrLen) { - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + char *newbuffer = static_cast(realloc(buffer, maxStrLen + 1)); if (newbuffer) { buffer = newbuffer; capacity = maxStrLen; @@ -207,7 +207,7 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length) return *this; } len = length; - strcpy_P(buffer, (PGM_P)pstr); + strcpy_P(buffer, reinterpret_cast(pstr)); return *this; } @@ -253,7 +253,7 @@ String & String::operator = (const char *cstr) String & String::operator = (const __FlashStringHelper *pstr) { - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); + if (pstr) copy(pstr, strlen_P(reinterpret_cast(pstr))); else invalidate(); return *this; @@ -343,11 +343,11 @@ bool String::concat(double num) bool String::concat(const __FlashStringHelper * str) { if (!str) return false; - int length = strlen_P((const char *) str); + int length = strlen_P(reinterpret_cast(str)); if (length == 0) return true; unsigned int newlen = len + length; if (!reserve(newlen)) return false; - strcpy_P(buffer + len, (const char *) str); + strcpy_P(buffer + len, reinterpret_cast(str)); len = newlen; return true; } @@ -440,8 +440,8 @@ StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHel int String::compareTo(const String &s) const { if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; + if (s.buffer && s.len > 0) return 0 - *(reinterpret_cast(s.buffer)); + if (buffer && len > 0) return *(reinterpret_cast(buffer)); return 0; } return strcmp(buffer, s.buffer); @@ -450,8 +450,8 @@ int String::compareTo(const String &s) const int String::compareTo(const char *cstr) const { if (!buffer || !cstr) { - if (cstr && *cstr) return 0 - *(unsigned char *)cstr; - if (buffer && len > 0) return *(unsigned char *)buffer; + if (cstr && *cstr) return 0 - *(const_cast(reinterpret_cast(cstr))); + if (buffer && len > 0) return *(reinterpret_cast(buffer)); return 0; } return strcmp(buffer, cstr); @@ -539,7 +539,7 @@ void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int ind } unsigned int n = bufsize - 1; if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); + strncpy(reinterpret_cast(buf), buffer + index, n); buf[n] = 0; } @@ -602,7 +602,7 @@ int String::lastIndexOf(const String &s2, unsigned int fromIndex) const for (char *p = buffer; p <= buffer + fromIndex; p++) { p = strstr(p, s2.buffer); if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; + if (static_cast(p - buffer) <= fromIndex) found = p - buffer; } return found; } @@ -685,7 +685,7 @@ void String::remove(unsigned int index){ // Pass the biggest integer as the count. The remove method // below will take care of truncating it at the end of the // string. - remove(index, (unsigned int)-1); + remove(index, static_cast(-1)); } void String::remove(unsigned int index, unsigned int count){ diff --git a/api/deprecated-avr-comp/avr/pgmspace.h b/api/deprecated-avr-comp/avr/pgmspace.h index 660c4dcd..a80e4a51 100644 --- a/api/deprecated-avr-comp/avr/pgmspace.h +++ b/api/deprecated-avr-comp/avr/pgmspace.h @@ -100,48 +100,12 @@ typedef const void* uint_farptr_t; #define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) #define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) -#define vsprintf_P(s, f, ...) vsprintf((s), (f), __VA_ARGS__) -#define vsnprintf_P(s, f, ...) vsnprintf((s), (f), __VA_ARGS__) -#if 0 -// Requires natural aligned addresses #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define pgm_read_word(addr) (*(const unsigned short *)(addr)) #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) #define pgm_read_float(addr) (*(const float *)(addr)) #define pgm_read_ptr(addr) (*(void *const *)(addr)) -#else -// Supports misaligned addresses -#ifdef __cplusplus -extern "C"{ -#endif -static inline unsigned char pgm_read_byte(const void *addr) { - return *(const unsigned char *)(addr); -} -static inline unsigned short pgm_read_word(const void *addr) { - const unsigned char *a = (const unsigned char *)addr; - return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ); -} -static inline unsigned long pgm_read_dword(const void *addr) { - const unsigned char *a = (const unsigned char *)addr; - return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ) | ( pgm_read_byte(a + 2) << 16 ) | ( pgm_read_byte(a + 3) << 24 ); -} -static inline void *pgm_read_ptr(const void *addr) { - return (void*) pgm_read_dword(addr); -} -static inline float pgm_read_float(const void *addr) { - union { - void *p; - float f; - } x; - x.p = pgm_read_ptr(addr); - return x.f; -} -#ifdef __cplusplus -} -#endif - -#endif #define pgm_read_byte_near(addr) pgm_read_byte(addr) #define pgm_read_word_near(addr) pgm_read_word(addr) diff --git a/test/.gitignore b/test/.gitignore index c795b054..faa6a97b 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -1 +1,19 @@ -build \ No newline at end of file +build +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +CMakeUserPresets.json + +# External projects +*-prefix/ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 31b75483..d8050249 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,11 +8,20 @@ cmake_minimum_required(VERSION 2.8) project(test-ArduinoCore-API) +Include(FetchContent) + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.4.0 +) + +FetchContent_MakeAvailable(Catch2) + ########################################################################## include_directories(..) include_directories(include) -include_directories(external/catch/v2.13.9/include) ########################################################################## @@ -118,7 +127,6 @@ set(TEST_DUT_SRCS ########################################################################## set(TEST_TARGET_SRCS - src/main.cpp src/dtostrf.cpp src/itoa.cpp src/MillisFake.cpp @@ -144,5 +152,7 @@ add_executable( ${TEST_TARGET_SRCS} ) +target_link_libraries( ${TEST_TARGET} Catch2WithMain ) + ########################################################################## diff --git a/test/external/catch/v2.13.1/include/catch.hpp b/test/external/catch/v2.13.1/include/catch.hpp deleted file mode 100644 index 94e20c21..00000000 --- a/test/external/catch/v2.13.1/include/catch.hpp +++ /dev/null @@ -1,17802 +0,0 @@ -/* - * Catch v2.13.1 - * Generated: 2020-09-07 12:12:38.090364 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 1 - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -#ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { - unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif - -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif - -#endif - -#if defined(__cpp_lib_uncaught_exceptions) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -// We have to avoid both ICC and Clang, because they try to mask themselves -// as gcc, and we want only GCC in this block -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) - -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) - -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ -# endif - -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Not all Windows environments support SEH properly -#if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#endif - -//////////////////////////////////////////////////////////////////////////////// -// PS4 -#if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) - -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -# endif -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#if defined(_MSC_VER) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) - -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__clang__) // Handle Clang masquerading for msvc -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif // MSVC_TRADITIONAL -# endif // __clang__ - -#endif // _MSC_VER - -#if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is required -# define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// Check if we are compiled with -fno-exceptions or equivalent -#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED -#endif - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// RTX is a special version of Windows that is real time. -// This means that it is detected as Windows, but does not provide -// the same set of capabilities as real Windows does. -#if defined(UNDER_RTSS) || defined(RTX64_BUILD) - #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH - #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE -#endif - -#if !defined(_GLIBCXX_USE_C99_MATH_TR1) -#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Various stdlib support checks that require __has_include -#if defined(__has_include) - // Check if string_view is available and usable - #if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW - #endif - - // Check if optional is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if byte is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # include - # if __cpp_lib_byte > 0 - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # endif - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if variant is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 - # include - # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # define CATCH_CONFIG_NO_CPP17_VARIANT - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__clang__) && (__clang_major__ < 8) - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -# define CATCH_CONFIG_CPP17_BYTE -#endif - -#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN -#endif - -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -# define CATCH_CONFIG_USE_ASYNC -#endif - -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -# define CATCH_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Even if we do not think the compiler has that warning, we still have -// to provide a macro that can be used by the code. -#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -#endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - -#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#elif defined(__clang__) && (__clang_major__ < 5) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_TRY if ((true)) -#define CATCH_CATCH_ALL if ((false)) -#define CATCH_CATCH_ANON(type) if ((false)) -#else -#define CATCH_TRY try -#define CATCH_CATCH_ALL catch (...) -#define CATCH_CATCH_ANON(type) catch (type) -#endif - -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) -#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy {}; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); - -namespace Catch { - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; - - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; - - struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) - -// end catch_common.h -namespace Catch { - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - - class TestSpec; - - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include -#include - -namespace Catch { - - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; - - private: - static constexpr char const* const s_empty = ""; - - char const* m_start = s_empty; - size_type m_size = 0; - - public: // construction - constexpr StringRef() noexcept = default; - - StringRef( char const* rawChars ) noexcept; - - constexpr StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} - - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} - - explicit operator std::string() const { - return std::string(m_start, m_size); - } - - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } - - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; - - public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; - - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } - - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; - - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - - constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } -} // namespace Catch - -constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) -#else -// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) -#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) -#endif - -#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ -#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) -#else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) -#endif - -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) - -#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N - -#define INTERNAL_CATCH_TYPE_GEN\ - template struct TypeList {};\ - template\ - constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ - template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ - template\ - struct append;\ - template\ - struct rewrap;\ - template class, typename...>\ - struct create;\ - template class, typename>\ - struct convert;\ - \ - template \ - struct append { using type = T; };\ - template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ - template< template class L1, typename...E1, typename...Rest>\ - struct append, TypeList, Rest...> { using type = L1; };\ - \ - template< template class Container, template class List, typename...elems>\ - struct rewrap, List> { using type = TypeList>; };\ - template< template class Container, template class List, class...Elems, typename...Elements>\ - struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ - \ - template