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>
51 lines
1.2 KiB
C++
51 lines
1.2 KiB
C++
#ifndef __IMFHeader_h__
|
|
# define __IMFHeader_h__
|
|
|
|
# include "Parser.h"
|
|
# include "MString.h"
|
|
# include <map>
|
|
|
|
namespace coreutils {
|
|
|
|
///
|
|
/// IMFHeader parses a full block of IMF/MIME-style headers (RFC 5322
|
|
/// "name: value" pairs, one per line, with folded continuation lines -
|
|
/// any line starting with a space or tab is appended to the previous
|
|
/// field's value) from the shared StreamReader, stopping at the blank
|
|
/// line that terminates the header block. Resumable across any number of
|
|
/// StreamReader::feed() calls - partially-read names/values accumulate
|
|
/// in the name/field members rather than being discarded between calls.
|
|
///
|
|
|
|
class IMFHeader : public Parser {
|
|
|
|
public:
|
|
|
|
IMFHeader(StreamReader &reader);
|
|
|
|
///
|
|
/// Valid once doParse() has returned Status::COMPLETE - every header
|
|
/// field parsed, keyed by field name.
|
|
///
|
|
|
|
std::map<MString, MString> &getHeaders();
|
|
|
|
protected:
|
|
|
|
Status parse() override;
|
|
|
|
private:
|
|
|
|
enum State { NAME, SKIP_SPACE, FIELD, FOLD_CHECK } state = NAME;
|
|
MString name;
|
|
MString field;
|
|
std::map<MString, MString> headers;
|
|
|
|
void commitField();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|