Introduces StreamReader to accumulate socket data delivered in arbitrary chunks into one buffer, so a Parser can build an object (a line, a header block, a MIME boundary) that spans any number of packets without losing its place. Parser is redesigned around this: no longer inherits MString (was redundant with its own buffer member), takes a StreamReader&, and drives a resumable COMPLETE/INCOMPLETE/DATA_AVAIL state-machine protocol via doParse(). LineParser, IMFHeader, and IMFBoundary are rewritten as real, working resumable parsers against the shared buffer instead of the previous non-compiling stubs (mismatched constructors/return types, a syntax error, checkParse() never implemented). IMFFormData is left as the stub it already was, just restored to compiling against the new IMFHeader signature - fully wiring it up needs IMFMultipart/IMFText migrated to StreamReader too, out of scope here. Verified with real runtime tests (not just compilation) covering data split mid-line, mid-CRLF, mid-header-fold, and mid-boundary-marker across separate feed() calls, plus StreamReader::compact(). Along the way fixed a header-value bug (space after ':' wasn't skipped) and a double cursor-offset subtraction bug in two places caused by forgetting that ZString::getLength() is already cursor-relative, not the raw buffer size. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
50 lines
1.5 KiB
C++
50 lines
1.5 KiB
C++
#include "IMFBoundary.h"
|
|
#include "Exception.h"
|
|
|
|
namespace coreutils {
|
|
|
|
IMFBoundary::IMFBoundary(StreamReader &reader, ZString boundary) : Parser(reader), boundary(boundary) {}
|
|
|
|
Parser::Status IMFBoundary::parse() {
|
|
MString &buffer = reader.getBuffer();
|
|
switch (state) {
|
|
|
|
case PREFIX: {
|
|
MString marker;
|
|
marker << "\r\n--";
|
|
marker << boundary;
|
|
int pos = buffer.find(marker);
|
|
if (pos < 0)
|
|
return Status::INCOMPLETE;
|
|
if (!buffer.ifNext(marker))
|
|
throw coreutils::Exception("IMFBoundary: boundary marker vanished between find and ifNext.");
|
|
state = TAIL;
|
|
return Status::DATA_AVAIL;
|
|
}
|
|
|
|
case TAIL:
|
|
// ZString::getLength() is already cursor-relative (bytes remaining
|
|
// from the cursor to the end) - do not subtract the cursor offset
|
|
// again here.
|
|
if (buffer.getLength() < 2)
|
|
return Status::INCOMPLETE;
|
|
if (buffer.ifNext(ZString("--"))) {
|
|
last = true;
|
|
return Status::COMPLETE;
|
|
}
|
|
if (buffer.ifNext(ZString("\r\n"))) {
|
|
last = false;
|
|
return Status::COMPLETE;
|
|
}
|
|
throw coreutils::Exception("IMFBoundary: malformed boundary line - expected CRLF or trailing --.");
|
|
|
|
}
|
|
throw coreutils::Exception("IMFBoundary: unreachable state.");
|
|
}
|
|
|
|
bool IMFBoundary::isLast() {
|
|
return last;
|
|
}
|
|
|
|
}
|