// // VMime library (http://www.vmime.org) // Copyright (C) 2002 Vincent Richard // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 3 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // Linking this library statically or dynamically with other modules is making // a combined work based on this library. Thus, the terms and conditions of // the GNU General Public License cover the whole combination. // #include "vmime/component.hpp" #include "vmime/base.hpp" #include "vmime/utility/streamUtils.hpp" #include "vmime/utility/inputStreamStringAdapter.hpp" #include "vmime/utility/outputStreamAdapter.hpp" #include namespace vmime { component::component() : m_parsedOffset(0), m_parsedLength(0) { } component::~component() { } void component::parse( const shared_ptr & inputStream, const size_t length ) { parse(inputStream, 0, length, NULL); } void component::parse( const shared_ptr & inputStream, const size_t position, const size_t end, size_t* newPosition) { parse(parsingContext::getDefaultContext(), inputStream, position, end, newPosition); } void component::parse( const parsingContext& ctx, const shared_ptr & inputStream, const size_t position, const size_t end, size_t* newPosition ) { m_parsedOffset = m_parsedLength = 0; shared_ptr seekableStream = dynamicCast (inputStream); if (!seekableStream || 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(ctx, buffer, 0, buffer.length(), NULL); } else { shared_ptr parser = make_shared (seekableStream); parseImpl(ctx, parser, position, end, newPosition); } } void component::parse(const string& buffer) { m_parsedOffset = m_parsedLength = 0; parseImpl(parsingContext::getDefaultContext(), buffer, 0, buffer.length(), NULL); } void component::parse(const parsingContext& ctx, const string& buffer) { m_parsedOffset = m_parsedLength = 0; parseImpl(ctx, buffer, 0, buffer.length(), NULL); } void component::parse( const string& buffer, const size_t position, const size_t end, size_t* newPosition ) { m_parsedOffset = m_parsedLength = 0; parseImpl(parsingContext::getDefaultContext(), buffer, position, end, newPosition); } void component::parse( const parsingContext& ctx, const string& buffer, const size_t position, const size_t end, size_t* newPosition ) { m_parsedOffset = m_parsedLength = 0; parseImpl(ctx, buffer, position, end, newPosition); } void component::offsetParsedBounds(const size_t 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 (size_t i = 0, n = children.size() ; i < n ; ++i) { children[i]->offsetParsedBounds(offset); } } void component::parseImpl( const parsingContext& ctx, const shared_ptr & parser, const size_t position, const size_t end, size_t* newPosition ) { // This is the default implementation for parsing from an input stream: // actually, we extract the substring and use the "parse from string" implementation const string buffer = parser->extract(position, end); parseImpl(ctx, buffer, 0, buffer.length(), newPosition); // Recursivey offset parsed bounds on children if (position != 0) { offsetParsedBounds(position); } if (newPosition) { *newPosition += position; } } void component::parseImpl( const parsingContext& ctx, const string& buffer, const size_t position, const size_t end, size_t* newPosition) { // This is the default implementation for parsing from a string: // actually, we encapsulate the string buffer in an input stream, then use // the "parse from input stream" implementation shared_ptr stream = make_shared (buffer); shared_ptr parser = make_shared (stream); parseImpl(ctx, parser, position, end, newPosition); } const string component::generate( const size_t maxLineLength, const size_t curLinePos ) const { std::ostringstream oss; utility::outputStreamAdapter adapter(oss); generationContext ctx(generationContext::getDefaultContext()); ctx.setMaxLineLength(maxLineLength); generateImpl(ctx, adapter, curLinePos, NULL); return oss.str(); } void component::generate( utility::outputStream& os, const size_t curLinePos, size_t* newLinePos ) const { generateImpl(generationContext::getDefaultContext(), os, curLinePos, newLinePos); } void component::generate( const generationContext& ctx, utility::outputStream& outputStream, const size_t curLinePos, size_t* newLinePos ) const { generateImpl(ctx, outputStream, curLinePos, newLinePos); } size_t component::getParsedOffset() const { return m_parsedOffset; } size_t component::getParsedLength() const { return m_parsedLength; } void component::setParsedBounds(const size_t start, const size_t end) { m_parsedOffset = start; m_parsedLength = end - start; } size_t component::getGeneratedSize(const generationContext& ctx) { std::vector > children = getChildComponents(); size_t totalSize = 0; for (std::vector >::iterator it = children.begin() ; it != children.end() ; ++it) { totalSize += (*it)->getGeneratedSize(ctx); } return totalSize; } } // vmime