diff --git a/api/Stream.cpp b/api/Stream.cpp index f6f9bda6..df361997 100644 --- a/api/Stream.cpp +++ b/api/Stream.cpp @@ -255,6 +255,14 @@ String Stream::readStringUntil(char terminator) return ret; } +String Stream::readLine() +{ + String ret = readStringUntil('\n'); + if (ret.endsWith("\r")) + ret.remove(ret.length()-1); + return ret; +} + int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { // any zero length target string automatically matches and would make // a mess of the rest of the algorithm. diff --git a/api/Stream.h b/api/Stream.h index e81c71ba..b407fd73 100644 --- a/api/Stream.h +++ b/api/Stream.h @@ -67,7 +67,7 @@ class Stream : public Print void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second 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); } // returns true if target string is found, false if timed out (see setTimeout) @@ -107,6 +107,7 @@ class Stream : public Print // Arduino String functions to be added here String readString(); String readStringUntil(char terminator); + String readLine(); protected: long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } @@ -130,4 +131,4 @@ class Stream : public Print } -using arduino::Stream; \ No newline at end of file +using arduino::Stream; diff --git a/api/String.cpp b/api/String.cpp index 4f176374..a13d6b82 100644 --- a/api/String.cpp +++ b/api/String.cpp @@ -625,6 +625,18 @@ String String::substring(unsigned int left, unsigned int right) const /* Modification */ /*********************************************/ +void String::insert(const String &str, unsigned int index, unsigned int length) +{ + if (index > len) return; + length = length < str.len ? length : str.len; + unsigned int size = len + length; + if (size > capacity && !reserve(size)) return; // XXX: tell user! + memmove(buffer + index + length, buffer + index, len - index + 1); + memcpy(buffer + index, str.buffer, length); + len += length; + return; +} + void String::replace(char find, char replace) { if (!buffer) return; diff --git a/api/String.h b/api/String.h index 73a872de..380fc4e1 100644 --- a/api/String.h +++ b/api/String.h @@ -202,6 +202,8 @@ class String String substring( unsigned int beginIndex, unsigned int endIndex ) const; // modification + void insert(char c, unsigned int index) { return insert(String(c), index, 1); }; + void insert(const String &str, unsigned int index, unsigned int length); void replace(char find, char replace); void replace(const String& find, const String& replace); void remove(unsigned int index); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f6bcc123..9deb8feb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -69,6 +69,7 @@ set(TEST_SRCS src/Stream/test_parseInt.cpp src/Stream/test_readBytes.cpp src/Stream/test_readBytesUntil.cpp + src/Stream/test_readLine.cpp src/Stream/test_readString.cpp src/Stream/test_readStringUntil.cpp src/Stream/test_setTimeout.cpp @@ -81,6 +82,7 @@ set(TEST_SRCS src/String/test_indexOf.cpp src/String/test_lastIndexOf.cpp src/String/test_length.cpp + src/String/test_insert.cpp src/String/test_move.cpp src/String/test_remove.cpp src/String/test_replace.cpp diff --git a/test/src/Stream/test_readLine.cpp b/test/src/Stream/test_readLine.cpp new file mode 100644 index 00000000..29455048 --- /dev/null +++ b/test/src/Stream/test_readLine.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Arduino. All rights reserved. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +#include +#include + +/************************************************************************************** + * TEST CODE + **************************************************************************************/ + +TEST_CASE ("Testing 'readLine' with no EOL character", "[Stream-readLine-01]") +{ + StreamMock mock; + mock.setTimeout(10); + millis_autoOn(); + mock << "Hello Arduino"; + REQUIRE(mock.readLine() == arduino::String("Hello Arduino")); +} + +TEST_CASE ("Testing 'readLine' with Unix EOL character", "[Stream-readLine-02]") +{ + StreamMock mock; + mock.setTimeout(10); + millis_autoOn(); + mock << "Hello\nArduino\n"; + REQUIRE(mock.readLine() == arduino::String("Hello")); +} + +TEST_CASE ("Testing 'readLine' with DOS EOL character", "[Stream-readLine-03]") +{ + StreamMock mock; + mock.setTimeout(10); + millis_autoOn(); + mock << "Hello\r\nArduino\r\n"; + REQUIRE(mock.readLine() == arduino::String("Hello")); +} diff --git a/test/src/String/test_insert.cpp b/test/src/String/test_insert.cpp new file mode 100644 index 00000000..4ef708b3 --- /dev/null +++ b/test/src/String/test_insert.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Arduino. All rights reserved. + */ + +/************************************************************************************** + * INCLUDE + **************************************************************************************/ + +#include + +#include + +#include "StringPrinter.h" + +/************************************************************************************** + * TEST CODE + **************************************************************************************/ + +TEST_CASE ("Testing String::insert(char, index)", "[String-insert-01]") +{ + arduino::String str = "ello"; + str.insert('h', 0); + REQUIRE(str == String("hello")); +} + +TEST_CASE ("Testing String::insert(char, index) with index > length", "[String-insert-02]") +{ + arduino::String str = "Hello Arduino"; + str.insert('!', str.length() + 1); + REQUIRE(str == String("Hello Arduino")); +} + + +TEST_CASE ("Testing String::insert(String, index, length) with length >= inserted length", "[String-insert-03]") +{ + arduino::String str = "hello "; + str.insert("world", str.length(), 5); + REQUIRE(str == String("hello world")); +} + +TEST_CASE ("Testing String::insert(String, index, length) with length < inserted length", "[String-insert-04]") +{ + arduino::String str = "Hello "; + str.insert("Arduino 1234", str.length(), 7); + REQUIRE(str == String("Hello Arduino")); +} +