Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f013f08

Browse files
committed
ESP8266WebServer - StreamString parsing experiment
impl based on esp8266#9005, but for existing Arduino methods
1 parent c2f1365 commit f013f08

File tree

3 files changed

+67
-38
lines changed

3 files changed

+67
-38
lines changed

‎cores/esp8266/Stream.cpp‎

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@
2020
parsing functions based on TextFinder library by Michael Margolis
2121
*/
2222

23-
#include <Arduino.h>
24-
#include <Stream.h>
23+
#include "Arduino.h"
24+
#include "Stream.h"
25+
#include "StreamString.h"
2526

2627
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
2728
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
@@ -254,34 +255,45 @@ String Stream::readString() {
254255

255256
String Stream::readStringUntil(char terminator) {
256257
String ret;
257-
int c = timedRead();
258-
while(c >= 0 && c != terminator) {
259-
ret += (char) c;
260-
c = timedRead();
261-
}
258+
259+
S2Stream s2s(ret);
260+
sendUntil(s2s, terminator, _timeout);
261+
262262
return ret;
263263
}
264264

265265
String Stream::readStringUntil(const char* terminator, uint32_t untilTotalNumberOfOccurrences) {
266266
String ret;
267-
int c;
267+
if (!untilTotalNumberOfOccurrences) {
268+
return ret;
269+
}
270+
271+
const size_t termLen = strlen_P(terminator);
272+
if (!termLen) {
273+
return ret;
274+
}
275+
276+
S2Stream s2s(ret);
268277
uint32_t occurrences = 0;
269-
size_t termLen = strlen(terminator);
270-
size_t termIndex = 0;
271-
size_t index = 0;
278+
const size_t tailLen = termLen - 1;
272279

273-
while ((c = timedRead()) > 0) {
274-
ret += (char) c;
275-
index++;
280+
for (;;) {
281+
sendUntil(s2s, terminator[tailLen], _timeout);
282+
if (s2s.getLastSendReport() != Stream::Report::Success) {
283+
break;
284+
}
285+
286+
if ((ret.length() >= tailLen)
287+
&& ((0 == tailLen) || (0 == memcmp_P(terminator, ret.end() - tailLen, tailLen))))
288+
{
289+
++occurrences;
290+
}
276291

277-
if (terminator[termIndex] == c) {
278-
if (++termIndex == termLen && ++occurrences == untilTotalNumberOfOccurrences) {
279-
// don't include terminator in returned string
280-
ret.remove(index - termIndex, termLen);
281-
break;
292+
if (untilTotalNumberOfOccurrences == occurrences) {
293+
if (tailLen) {
294+
ret.remove(ret.length() - tailLen);
282295
}
283-
} else {
284-
termIndex = 0;
296+
break;
285297
}
286298
}
287299

‎libraries/ESP8266WebServer/src/Parsing-impl.h‎

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,8 @@ static bool readBytesWithTimeout(typename ServerType::ClientType& client, size_t
4444
template <typename ServerType>
4545
typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
4646
// Read the first line of HTTP request
47-
String req = client.readStringUntil('\r');
47+
String req = client.readStringUntil("\r\n");
4848
DBGWS("request: %s\n", req.c_str());
49-
client.readStringUntil('\n');
5049
//reset header value
5150
for (int i = 0; i < _headerKeysCount; ++i) {
5251
_currentHeaders[i].value.clear();
@@ -122,8 +121,7 @@ typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemp
122121
uint32_t contentLength = 0;
123122
//parse headers
124123
while(1){
125-
req = client.readStringUntil('\r');
126-
client.readStringUntil('\n');
124+
req = client.readStringUntil("\r\n");
127125
if (req.isEmpty()) break; //no more headers
128126
int headerDiv = req.indexOf(':');
129127
if (headerDiv == -1){
@@ -198,8 +196,7 @@ typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemp
198196
String headerValue;
199197
//parse headers
200198
while(1){
201-
req = client.readStringUntil('\r');
202-
client.readStringUntil('\n');
199+
req = client.readStringUntil("\r\n");
203200
if (req.isEmpty()) break;//no moar headers
204201
int headerDiv = req.indexOf(':');
205202
if (headerDiv == -1){
@@ -351,7 +348,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
351348
String line;
352349
int retry = 0;
353350
do {
354-
line = client.readStringUntil('\r');
351+
line = client.readStringUntil("\r\n");
355352
++retry;
356353
} while (line.length() == 0 && retry < 3);
357354

@@ -367,8 +364,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
367364
String argFilename;
368365
bool argIsFile = false;
369366

370-
line = client.readStringUntil('\r');
371-
client.readStringUntil('\n');
367+
line = client.readStringUntil("\r\n");
372368
if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))){
373369
int nameStart = line.indexOf('=');
374370
if (nameStart != -1){
@@ -388,19 +384,16 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
388384
DBGWS("PostArg Name: %s\n", argName.c_str());
389385
using namespace mime;
390386
argType = FPSTR(mimeTable[txt].mimeType);
391-
line = client.readStringUntil('\r');
392-
client.readStringUntil('\n');
387+
line = client.readStringUntil("\r\n");
393388
if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))){
394389
argType = line.substring(line.indexOf(':')+2);
395390
//skip next line
396-
client.readStringUntil('\r');
397-
client.readStringUntil('\n');
391+
client.readStringUntil("\r\n");
398392
}
399393
DBGWS("PostArg Type: %s\n", argType.c_str());
400394
if (!argIsFile){
401395
while(1){
402-
line = client.readStringUntil('\r');
403-
client.readStringUntil('\n');
396+
line = client.readStringUntil("\r\n");
404397
if (line.startsWith("--"+boundary)) break;
405398
if (argValue.length() > 0) argValue += '\n';
406399
argValue += line;
@@ -474,8 +467,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
474467
_currentUpload->type.c_str(),
475468
(int)_currentUpload->totalSize);
476469
if (!client.connected()) return _parseFormUploadAborted();
477-
line = client.readStringUntil('\r');
478-
client.readStringUntil('\n');
470+
line = client.readStringUntil("\r\n");
479471
if (line == "--") { // extra two dashes mean we reached the end of all form fields
480472
DBGWS("Done Parsing POST\n");
481473
break;

‎tests/host/core/test_string.cpp‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,31 @@ TEST_CASE("Issue #2736 - StreamString SSO fix", "[core][StreamString]")
512512
REQUIRE(s == "{\"message\"");
513513
}
514514

515+
TEST_CASE("Issue #9005 - StreamString for Stream->String conversion", "[core][StreamString]")
516+
{
517+
const char buffer[] =
518+
"this is a test string"
519+
"\r\n"
520+
"delimited as if it was a http request"
521+
"\r\n"
522+
"\r\n";
523+
524+
StreamString input;
525+
input.print(buffer);
526+
REQUIRE(input == buffer);
527+
528+
String out = input.readStringUntil("\r\n");
529+
REQUIRE(21 == out.length());
530+
REQUIRE(out == "this is a test string");
531+
532+
out = input.readStringUntil("\r\n");
533+
REQUIRE(37 == out.length());
534+
REQUIRE(out == "delimited as if it was a http request");
535+
536+
out = input.readStringUntil("\r\n");
537+
REQUIRE(0 == out.length());
538+
}
539+
515540
TEST_CASE("Strings with NULs", "[core][String]")
516541
{
517542
// The following should never be done in a real app! This is only to inject 0s in the middle of

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /