Added progression notifications.

This commit is contained in:
Vincent Richard 2005-09-03 12:48:59 +00:00
parent df140bb13e
commit f777b659b9
22 changed files with 310 additions and 46 deletions

View File

@ -2,6 +2,10 @@
VERSION 0.7.2cvs
================
2005-09-03 Vincent Richard <vincent@vincent-richard.net>
* encoder*, *contentHandler: added progression notifications.
2005-08-25 Vincent Richard <vincent@vincent-richard.net>
* Tests: moved to CppUnit for unit tests framework.

View File

@ -153,7 +153,7 @@ libvmime_sources = [
'utility/filteredStream.cpp', 'utility/filteredStream.hpp',
'utility/md5.cpp', 'utility/md5.hpp',
'utility/path.cpp', 'utility/path.hpp',
'utility/progressionListener.hpp',
'utility/progressionListener.cpp', 'utility/progressionListener.hpp',
'utility/random.cpp', 'utility/random.hpp',
'utility/smartPtr.hpp',
'utility/stream.cpp', 'utility/stream.hpp',

View File

@ -42,15 +42,29 @@ void emptyContentHandler::generate(utility::outputStream& /* os */, const vmime:
}
void emptyContentHandler::extract(utility::outputStream& /* os */) const
void emptyContentHandler::extract(utility::outputStream& /* os */,
utility::progressionListener* progress) const
{
if (progress)
progress->start(0);
// Nothing to do.
if (progress)
progress->stop(0);
}
void emptyContentHandler::extractRaw(utility::outputStream& /* os */) const
void emptyContentHandler::extractRaw(utility::outputStream& /* os */,
utility::progressionListener* progress) const
{
if (progress)
progress->start(0);
// Nothing to do.
if (progress)
progress->stop(0);
}

View File

@ -70,7 +70,8 @@ const unsigned char encoderB64::sm_decodeMap[256] =
const utility::stream::size_type encoderB64::encode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderB64::encode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -88,9 +89,13 @@ const utility::stream::size_type encoderB64::encode(utility::inputStream& in, ut
unsigned char output[4];
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
int curCol = 0;
if (progress)
progress->start(0);
while (bufferPos < bufferLength || !in.eof())
{
if (bufferPos >= bufferLength)
@ -156,6 +161,7 @@ const utility::stream::size_type encoderB64::encode(utility::inputStream& in, ut
// Write encoded data to output stream
B64_WRITE(out, output, 4);
inTotal += count;
total += 4;
curCol += 4;
@ -164,13 +170,20 @@ const utility::stream::size_type encoderB64::encode(utility::inputStream& in, ut
out.write("\r\n", 2);
curCol = 0;
}
if (progress)
progress->progress(inTotal, inTotal);
}
if (progress)
progress->stop(inTotal);
return (total);
}
const utility::stream::size_type encoderB64::decode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderB64::decode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -180,10 +193,14 @@ const utility::stream::size_type encoderB64::decode(utility::inputStream& in, ut
int bufferPos = 0;
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
unsigned char bytes[4];
unsigned char output[3];
if (progress)
progress->start(0);
while (bufferPos < bufferLength || !in.eof())
{
bytes[0] = '=';
@ -265,8 +282,15 @@ const utility::stream::size_type encoderB64::decode(utility::inputStream& in, ut
B64_WRITE(out, output, 3);
total += 3;
inTotal += count;
if (progress)
progress->progress(inTotal, inTotal);
}
if (progress)
progress->stop(inTotal);
return (total);
}

View File

@ -29,21 +29,37 @@ encoderDefault::encoderDefault()
}
const utility::stream::size_type encoderDefault::encode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderDefault::encode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
// No encoding performed
return (utility::bufferedStreamCopy(in, out));
utility::stream::size_type res = 0;
if (progress)
res = utility::bufferedStreamCopy(in, out, 0, progress);
else
res = utility::bufferedStreamCopy(in, out);
return res;
}
const utility::stream::size_type encoderDefault::decode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderDefault::decode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
// No decoding performed
return (utility::bufferedStreamCopy(in, out));
utility::stream::size_type res = 0;
if (progress)
res = utility::bufferedStreamCopy(in, out, 0, progress);
else
res = utility::bufferedStreamCopy(in, out);
return res;
}

View File

@ -85,7 +85,8 @@ const unsigned char encoderQP::sm_hexDecodeTable[256] =
#endif // VMIME_BUILDING_DOC
const utility::stream::size_type encoderQP::encode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderQP::encode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -109,6 +110,10 @@ const utility::stream::size_type encoderQP::encode(utility::inputStream& in, uti
int outBufferPos = 0;
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
if (progress)
progress->start(0);
while (bufferPos < bufferLength || !in.eof())
{
@ -267,6 +272,11 @@ const utility::stream::size_type encoderQP::encode(utility::inputStream& in, uti
outBufferPos += 3;
curCol = 0;
}
++inTotal;
if (progress)
progress->progress(inTotal, inTotal);
}
// Flush remaining output buffer
@ -276,11 +286,15 @@ const utility::stream::size_type encoderQP::encode(utility::inputStream& in, uti
total += outBufferPos;
}
if (progress)
progress->stop(inTotal);
return (total);
}
const utility::stream::size_type encoderQP::decode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderQP::decode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -295,6 +309,7 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
int outBufferPos = 0;
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
while (bufferPos < bufferLength || !in.eof())
{
@ -321,6 +336,8 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
// Decode the next sequence (hex-encoded byte or printable character)
unsigned char c = static_cast <unsigned char>(buffer[bufferPos++]);
++inTotal;
switch (c)
{
case '=':
@ -335,6 +352,8 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
{
c = static_cast <unsigned char>(buffer[bufferPos++]);
++inTotal;
switch (c)
{
// Ignore soft line break ("=\r\n" or "=\n")
@ -348,7 +367,10 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
}
if (bufferPos < bufferLength)
{
++bufferPos;
++inTotal;
}
break;
@ -370,6 +392,8 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
{
const unsigned char next = static_cast <unsigned char>(buffer[bufferPos++]);
++inTotal;
const unsigned char value =
sm_hexDecodeTable[c] * 16
+ sm_hexDecodeTable[next];
@ -412,6 +436,9 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
}
}
if (progress)
progress->progress(inTotal, inTotal);
}
// Flush remaining output buffer
@ -421,6 +448,9 @@ const utility::stream::size_type encoderQP::decode(utility::inputStream& in, uti
total += outBufferPos;
}
if (progress)
progress->stop(inTotal);
return (total);
}

View File

@ -59,7 +59,8 @@ static inline const unsigned char UUDECODE(const unsigned char c)
}
const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderUUE::encode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -71,6 +72,7 @@ const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, ut
static_cast <string::size_type>(46));
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
// Output the prelude text ("begin [mode] [filename]")
out << "begin";
@ -88,6 +90,9 @@ const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, ut
utility::stream::value_type inBuffer[64];
utility::stream::value_type outBuffer[64];
if (progress)
progress->start(0);
while (!in.eof())
{
// Process up to 45 characters per line
@ -117,16 +122,24 @@ const utility::stream::size_type encoderUUE::encode(utility::inputStream& in, ut
out.write(outBuffer, j + 2);
total += j + 2;
inTotal += inLength;
if (progress)
progress->progress(inTotal, inTotal);
}
out << "end\r\n";
total += 5;
if (progress)
progress->stop(inTotal);
return (total);
}
const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, utility::outputStream& out)
const utility::stream::size_type encoderUUE::decode(utility::inputStream& in,
utility::outputStream& out, utility::progressionListener* progress)
{
in.reset(); // may not work...
@ -135,11 +148,15 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
utility::stream::value_type outBuffer[64];
utility::stream::size_type total = 0;
utility::stream::size_type inTotal = 0;
bool stop = false;
std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
if (progress)
progress->start(0);
while (!stop && !in.eof())
{
// Get the line length
@ -175,6 +192,8 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
inBuffer[3] == 'n' &&
parserHelpers::isSpace(inBuffer[4]))
{
inTotal += 5;
utility::stream::value_type c = 0;
utility::stream::size_type count = 0;
@ -188,9 +207,15 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
buffer[count++] = c;
}
inTotal += count;
if (c != '\n')
{
// OOPS! Weird line. Don't try to decode more...
if (progress)
progress->stop(inTotal);
return (total);
}
@ -240,6 +265,7 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
(inBuffer[2] == '\r' || inBuffer[2] == '\n'))
{
stop = true;
inTotal += 3;
continue;
}
@ -255,6 +281,8 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
break;
}
inTotal += (inLength - inPos);
// Decode data
for (utility::stream::size_type i = 0, j = 0 ; i < inLength ; i += 4, j += 3)
{
@ -281,8 +309,14 @@ const utility::stream::size_type encoderUUE::decode(utility::inputStream& in, ut
out.write(outBuffer, outLength);
std::fill(inBuffer, inBuffer + sizeof(inBuffer), 0);
if (progress)
progress->progress(inTotal, inTotal);
}
if (progress)
progress->stop(inTotal);
return (total);
}

View File

@ -128,7 +128,8 @@ void streamContentHandler::generate(utility::outputStream& os, const vmime::enco
}
void streamContentHandler::extract(utility::outputStream& os) const
void streamContentHandler::extract(utility::outputStream& os,
utility::progressionListener* progress) const
{
if (!m_stream)
return;
@ -138,6 +139,9 @@ void streamContentHandler::extract(utility::outputStream& os) const
{
m_stream->reset(); // may not work...
if (progress)
utility::bufferedStreamCopy(*m_stream, os, getLength(), progress);
else
utility::bufferedStreamCopy(*m_stream, os);
}
// Need to decode data
@ -147,18 +151,24 @@ void streamContentHandler::extract(utility::outputStream& os) const
m_stream->reset(); // may not work...
theDecoder->decode(*m_stream, os);
utility::progressionListenerSizeAdapter plsa(progress, getLength());
theDecoder->decode(*m_stream, os, &plsa);
}
}
void streamContentHandler::extractRaw(utility::outputStream& os) const
void streamContentHandler::extractRaw(utility::outputStream& os,
utility::progressionListener* progress) const
{
if (!m_stream)
return;
m_stream->reset(); // may not work...
if (progress)
utility::bufferedStreamCopy(*m_stream, os, getLength(), progress);
else
utility::bufferedStreamCopy(*m_stream, os);
}

View File

@ -146,12 +146,13 @@ void stringContentHandler::generate(utility::outputStream& os,
}
void stringContentHandler::extract(utility::outputStream& os) const
void stringContentHandler::extract(utility::outputStream& os,
utility::progressionListener* progress) const
{
// No decoding to perform
if (!isEncoded())
{
m_string.extract(os);
m_string.extract(os, 0, m_string.length(), progress);
}
// Need to decode data
else
@ -159,15 +160,17 @@ void stringContentHandler::extract(utility::outputStream& os) const
ref <encoder> theDecoder = m_encoding.getEncoder();
utility::inputStreamStringProxyAdapter in(m_string);
utility::progressionListenerSizeAdapter plsa(progress, getLength());
theDecoder->decode(in, os);
theDecoder->decode(in, os, &plsa);
}
}
void stringContentHandler::extractRaw(utility::outputStream& os) const
void stringContentHandler::extractRaw(utility::outputStream& os,
utility::progressionListener* progress) const
{
m_string.extract(os);
m_string.extract(os, 0, m_string.length(), progress);
}

View File

@ -0,0 +1,75 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
//
// 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "vmime/utility/progressionListener.hpp"
namespace vmime {
namespace utility {
// progressionListenerSizeAdapter
progressionListenerSizeAdapter::progressionListenerSizeAdapter
(progressionListener* list, const int total)
: m_wrapped(list), m_total(total)
{
}
const bool progressionListenerSizeAdapter::cancel() const
{
return (m_wrapped ? m_wrapped->cancel() : false);
}
void progressionListenerSizeAdapter::start(const int predictedTotal)
{
if (m_wrapped)
m_wrapped->start(predictedTotal);
}
void progressionListenerSizeAdapter::progress(const int current, const int currentTotal)
{
if (m_wrapped)
{
if (currentTotal > m_total)
m_total = currentTotal;
m_wrapped->progress(current, m_total);
}
}
void progressionListenerSizeAdapter::stop(const int total)
{
if (m_wrapped)
{
if (total > m_total)
m_total = total;
m_wrapped->stop(m_total);
}
}
} // utility
} // vmime

View File

@ -85,12 +85,26 @@ stringProxy& stringProxy::operator=(const string_type& s)
}
void stringProxy::extract(outputStream& os, const size_type start, const size_type end) const
void stringProxy::extract(outputStream& os, const size_type start, const size_type end,
utility::progressionListener* progress) const
{
size_type len = 0;
if (end == std::numeric_limits <size_type>::max())
os.write(m_buffer.data() + m_start + start, m_end - start - m_start);
else
os.write(m_buffer.data() + m_start + start, end - start - m_start);
len = m_end - start - m_start;
else if (end > start)
len = end - start - m_start;
if (progress)
progress->start(len);
os.write(m_buffer.data() + m_start + start, len);
if (progress)
{
progress->progress(len, len);
progress->stop(len);
}
}

View File

@ -26,6 +26,7 @@
#include "vmime/base.hpp"
#include "vmime/utility/stringProxy.hpp"
#include "vmime/utility/smartPtr.hpp"
#include "vmime/utility/progressionListener.hpp"
#include "vmime/encoding.hpp"
@ -66,16 +67,20 @@ public:
* @throw exceptions::no_encoder_available if the encoding is
* not supported
* @param os output stream
* @param progress progression listener, or NULL if you do not
* want to receive progression notifications
*/
virtual void extract(utility::outputStream& os) const = 0;
virtual void extract(utility::outputStream& os, utility::progressionListener* progress = NULL) const = 0;
/** Extract the contents into the specified stream, without
* decoding it. It may be useful in case the encoding is not
* supported and you want to extract raw data.
*
* @param os output stream
* @param progress progression listener, or NULL if you do not
* want to receive progression notifications
*/
virtual void extractRaw(utility::outputStream& os) const = 0;
virtual void extractRaw(utility::outputStream& os, utility::progressionListener* progress = NULL) const = 0;
/** Returns the actual length of data. WARNING: this can return 0 if no
* length was specified when setting data of this object.

View File

@ -38,8 +38,8 @@ public:
void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
void extract(utility::outputStream& os) const;
void extractRaw(utility::outputStream& os) const;
void extract(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
void extractRaw(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
const string::size_type getLength() const;

View File

@ -24,6 +24,7 @@
#include "vmime/base.hpp"
#include "vmime/propertySet.hpp"
#include "vmime/exception.hpp"
#include "vmime/utility/progressionListener.hpp"
namespace vmime
@ -44,17 +45,21 @@ public:
*
* @param in input data (decoded)
* @param out output stream for encoded data
* @param progress progression listener, or NULL if you do not
* want to receive progression notifications
* @return number of bytes written into output stream
*/
virtual const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out) = 0;
virtual const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL) = 0;
/** Decode data.
*
* @param in input data (encoded)
* @param out output stream for decoded data
* @param progress progression listener, or NULL if you do not
* want to receive progression notifications
* @return number of bytes written into output stream
*/
virtual const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out) = 0;
virtual const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL) = 0;
/** Return the properties of the encoder.
*

View File

@ -37,8 +37,8 @@ public:
encoderB64();
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const std::vector <string> getAvailableProperties() const;

View File

@ -37,8 +37,8 @@ public:
encoderDefault();
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
};

View File

@ -37,8 +37,8 @@ public:
encoderQP();
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const std::vector <string> getAvailableProperties() const;

View File

@ -37,8 +37,8 @@ public:
encoderUUE();
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out);
const utility::stream::size_type encode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const utility::stream::size_type decode(utility::inputStream& in, utility::outputStream& out, utility::progressionListener* progress = NULL);
const std::vector <string> getAvailableProperties() const;
};

View File

@ -47,8 +47,8 @@ public:
void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
void extract(utility::outputStream& os) const;
void extractRaw(utility::outputStream& os) const;
void extract(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
void extractRaw(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
const string::size_type getLength() const;

View File

@ -65,8 +65,8 @@ public:
void generate(utility::outputStream& os, const vmime::encoding& enc, const string::size_type maxLineLength = lineLengthLimits::infinite) const;
void extract(utility::outputStream& os) const;
void extractRaw(utility::outputStream& os) const;
void extract(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
void extractRaw(utility::outputStream& os, utility::progressionListener* progress = NULL) const;
const string::size_type getLength() const;

View File

@ -68,6 +68,35 @@ public:
};
/** A progression listener used when total size is known by the
* receiver, but not by the notifier.
*/
class progressionListenerSizeAdapter : public progressionListener
{
public:
/** Construct a new progressionListenerSizeAdapter object.
*
* @param list wrapped progression listener (can be NULL)
* @param total predicted total
*/
progressionListenerSizeAdapter(progressionListener* list, const int total);
const bool cancel() const;
void start(const int predictedTotal);
void progress(const int current, const int currentTotal);
void stop(const int total);
private:
progressionListener* m_wrapped;
int m_total;
};
} // utility
} // vmime

View File

@ -25,6 +25,7 @@
#include "vmime/types.hpp"
#include "vmime/utility/stream.hpp"
#include "vmime/utility/progressionListener.hpp"
namespace vmime {
@ -58,7 +59,7 @@ public:
// Extract some portion (or whole) of the string
// and output it into a stream.
void extract(outputStream& os, const size_type start = 0, const size_type end = std::numeric_limits <size_type>::max()) const;
void extract(outputStream& os, const size_type start = 0, const size_type end = std::numeric_limits <size_type>::max(), utility::progressionListener* progress = NULL) const;
// Return the "virtual" length of the string
const size_type length() const;