From 4f33877820edee1b47d1b6f4fc800eaad273adaa Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Mon, 16 Apr 2012 22:32:33 +0200 Subject: Added ability to parse directly from an input stream (eg. file). This allows very big messages to be parsed without loading the whole message data into memory. --- src/component.cpp | 137 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 118 insertions(+), 19 deletions(-) (limited to 'src/component.cpp') diff --git a/src/component.cpp b/src/component.cpp index 139cf664..e93aacf3 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -23,6 +23,9 @@ #include "vmime/component.hpp" #include "vmime/base.hpp" + +#include "vmime/utility/streamUtils.hpp" +#include "vmime/utility/inputStreamStringAdapter.hpp" #include "vmime/utility/outputStreamAdapter.hpp" #include @@ -43,9 +46,102 @@ component::~component() } +void component::parse + (ref inputStream, const utility::stream::size_type length) +{ + parse(inputStream, 0, length, NULL); +} + + +void component::parse + (ref inputStream, const utility::stream::size_type position, + const utility::stream::size_type end, utility::stream::size_type* newPosition) +{ + m_parsedOffset = m_parsedLength = 0; + + ref seekableStream = + inputStream.dynamicCast (); + + if (seekableStream == NULL || end == 0) + { + // Read the whole stream into a buffer + std::ostringstream oss; + utility::outputStreamAdapter ossAdapter(oss); + + utility::bufferedStreamCopyRange(*inputStream, ossAdapter, position, end - position); + + const string buffer = oss.str(); + parseImpl(buffer, 0, buffer.length(), NULL); + } + else + { + ref parser = + vmime::create (seekableStream); + + parseImpl(parser, position, end, newPosition); + } +} + + void component::parse(const string& buffer) { - parse(buffer, 0, buffer.length(), NULL); + m_parsedOffset = m_parsedLength = 0; + + parseImpl(buffer, 0, buffer.length(), NULL); +} + + +void component::parse + (const string& buffer, const string::size_type position, + const string::size_type end, string::size_type* newPosition) +{ + m_parsedOffset = m_parsedLength = 0; + + parseImpl(buffer, position, end, newPosition); +} + + +void component::offsetParsedBounds(const utility::stream::size_type offset) +{ + // Offset parsed bounds of this component + if (m_parsedLength != 0) + m_parsedOffset += offset; + + // Offset parsed bounds of our children + std::vector > children = getChildComponents(); + + for (unsigned int i = 0, n = children.size() ; i < n ; ++i) + children[i]->offsetParsedBounds(offset); +} + + +void component::parseImpl + (ref parser, const utility::stream::size_type position, + const utility::stream::size_type end, utility::stream::size_type* newPosition) +{ + const std::string buffer = parser->extract(position, end); + parseImpl(buffer, 0, buffer.length(), newPosition); + + // Recursivey offset parsed bounds on children + if (position != 0) + offsetParsedBounds(position); + + if (newPosition != NULL) + *newPosition += position; +} + + +void component::parseImpl + (const string& buffer, const string::size_type position, + const string::size_type end, string::size_type* newPosition) +{ + ref stream = + vmime::create (buffer); + + ref parser = + vmime::create (stream); + + parseImpl(parser, position, end, newPosition); } @@ -61,6 +157,26 @@ const string component::generate(const string::size_type maxLineLength, } +void component::generate + (utility::outputStream& os, + const string::size_type maxLineLength, + const string::size_type curLinePos, + string::size_type* newLinePos) const +{ + generateImpl(os, maxLineLength, curLinePos, newLinePos); +} + + +void component::generate + (ref os, + const string::size_type maxLineLength, + const string::size_type curLinePos, + string::size_type* newLinePos) const +{ + generateImpl(*os, maxLineLength, curLinePos, newLinePos); +} + + string::size_type component::getParsedOffset() const { return (m_parsedOffset); @@ -80,22 +196,5 @@ void component::setParsedBounds(const string::size_type start, const string::siz } -const std::vector > component::getChildComponents() -{ - const std::vector > constList = - const_cast (this)->getChildComponents(); - - std::vector > list; - - const std::vector >::size_type count = constList.size(); +} // vmime - list.resize(count); - - for (std::vector >::size_type i = 0 ; i < count ; ++i) - list[i] = constList[i].constCast (); - - return (list); -} - - -} -- cgit v1.2.3