Added filtered output stream to transform LFs to CRLFs.

This commit is contained in:
Vincent Richard 2013-04-16 12:03:13 +02:00
parent ff8827bdd3
commit 462311e382
4 changed files with 139 additions and 0 deletions

View File

@ -286,6 +286,77 @@ void CRLFToLFFilteredOutputStream::flush()
} }
// LFToCRLFFilteredOutputStream
LFToCRLFFilteredOutputStream::LFToCRLFFilteredOutputStream(outputStream& os)
: m_stream(os), m_previousChar('\0')
{
}
outputStream& LFToCRLFFilteredOutputStream::getNextOutputStream()
{
return (m_stream);
}
void LFToCRLFFilteredOutputStream::write
(const value_type* const data, const size_type count)
{
if (count == 0)
return;
std::string buffer;
buffer.reserve(count);
const value_type* pos = data;
const value_type* end = data + count;
value_type previousChar = m_previousChar;
while (pos < end)
{
switch (*pos)
{
case '\r':
buffer.append(1, '\r');
buffer.append(1, '\n');
break;
case '\n':
if (previousChar != '\r')
{
buffer.append(1, '\r');
buffer.append(1, '\n');
}
break;
default:
buffer.append(1, *pos);
break;
}
previousChar = *pos;
++pos;
}
m_stream.write(&buffer[0], buffer.length());
m_previousChar = previousChar;
}
void LFToCRLFFilteredOutputStream::flush()
{
m_stream.flush();
}
// stopSequenceFilteredInputStream <1> // stopSequenceFilteredInputStream <1>
template <> template <>

View File

@ -53,6 +53,8 @@
#define VASSERT_EQ(msg, expected, actual) \ #define VASSERT_EQ(msg, expected, actual) \
CPPUNIT_ASSERT_EQUAL_MESSAGE(std::string(msg), expected, actual) CPPUNIT_ASSERT_EQUAL_MESSAGE(std::string(msg), expected, actual)
#define VASSERT_NEQ(msg, expected, actual) \
CPPUNIT_ASSERT_MESSAGE(std::string(msg), (expected) != (actual))
#define VASSERT_THROW(msg, expression, exceptionType) \ #define VASSERT_THROW(msg, expression, exceptionType) \
CPPUNIT_ASSERT_THROW(expression, exceptionType) CPPUNIT_ASSERT_THROW(expression, exceptionType)

View File

@ -35,6 +35,8 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest)
VMIME_TEST(testStopSequenceFilteredInputStream1) VMIME_TEST(testStopSequenceFilteredInputStream1)
VMIME_TEST(testStopSequenceFilteredInputStreamN_2) VMIME_TEST(testStopSequenceFilteredInputStreamN_2)
VMIME_TEST(testStopSequenceFilteredInputStreamN_3) VMIME_TEST(testStopSequenceFilteredInputStreamN_3)
VMIME_TEST(testLFToCRLFFilteredOutputStream_Global)
VMIME_TEST(testLFToCRLFFilteredOutputStream_Edge)
VMIME_TEST_LIST_END VMIME_TEST_LIST_END
@ -276,5 +278,43 @@ VMIME_TEST_SUITE_BEGIN(filteredStreamTest)
testStopSequenceFISHelper <3>("24", "xyz", "", "x", "y", "z"); testStopSequenceFISHelper <3>("24", "xyz", "", "x", "y", "z");
} }
// LFToCRLFFilteredOutputStream
void testLFToCRLFFilteredOutputStream_Global()
{
typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER;
testFilteredOutputStreamHelper<FILTER>("1", "ABC\r\nDEF", "ABC\nDEF");
testFilteredOutputStreamHelper<FILTER>("2", "ABC\r\nDEF", "ABC\rDEF");
testFilteredOutputStreamHelper<FILTER>("3", "\r\n\r\nAB\r\n\r\nA\r\nB\r\n", "\n\nAB\n\nA\nB\n");
testFilteredOutputStreamHelper<FILTER>("4", "ABCDE\r\nF", "ABCDE\nF");
testFilteredOutputStreamHelper<FILTER>("5", "ABCDE\r\nF", "ABCDE\r\nF");
testFilteredOutputStreamHelper<FILTER>("6", "\r\n\r\n\r\n", "\n\n\n");
testFilteredOutputStreamHelper<FILTER>("7", "\r\n\r\n\r\n", "\r\r\n\n");
testFilteredOutputStreamHelper<FILTER>("8", "\r\n\r\n\r\n\r\n", "\r\r\r\r");
testFilteredOutputStreamHelper<FILTER>("9", "\r\n\r\n\r\n\r\n", "\n\n\n\n");
testFilteredOutputStreamHelper<FILTER>("10", "\r\n\r\n\r\n", "\r\n\n\n");
testFilteredOutputStreamHelper<FILTER>("11", "\r\n\r\n\r\n\r\n", "\n\n\n\r\n");
}
void testLFToCRLFFilteredOutputStream_Edge()
{
typedef vmime::utility::LFToCRLFFilteredOutputStream FILTER;
testFilteredOutputStreamHelper<FILTER>("1", "\r\n\r\n", "\r", "\r");
testFilteredOutputStreamHelper<FILTER>("2", "\r\n\r\n", "\r", "\n\r");
testFilteredOutputStreamHelper<FILTER>("3", "ABC\r\n\r\n", "ABC\r", "\n\r");
testFilteredOutputStreamHelper<FILTER>("4", "ABC\r\n\r\n\r\n", "ABC\r", "\n\r", "\n\n");
testFilteredOutputStreamHelper<FILTER>("5", "\r\n\r\n", "\n", "\n");
testFilteredOutputStreamHelper<FILTER>("6", "\r\n\r\n", "\r\n\r\n");
testFilteredOutputStreamHelper<FILTER>("7", "\r\n\r\n", "\r\n\r", "\n");
testFilteredOutputStreamHelper<FILTER>("8", "A\r\nB\r\nC\r\nD", "A\rB", "\nC\r\nD");
testFilteredOutputStreamHelper<FILTER>("9", "\r\nA\r\nB\r\nC\r\nD", "\rA\r", "B\nC\r\nD");
testFilteredOutputStreamHelper<FILTER>("10", "\r\nA\r\nB\r\nC\r\nD", "\nA\r", "B\nC\r\nD");
testFilteredOutputStreamHelper<FILTER>("11", "\r\nA\r\nB\r\nC\r\nD\r\n", "\nA\rB", "\nC\r\nD\r");
}
VMIME_TEST_SUITE_END VMIME_TEST_SUITE_END

View File

@ -155,6 +155,32 @@ private:
}; };
/** A filtered output stream which replaces CR or LF characters
* with CRLF sequences.
*/
class LFToCRLFFilteredOutputStream : public filteredOutputStream
{
public:
/** Construct a new filter for the specified output stream.
*
* @param os stream into which write filtered data
*/
LFToCRLFFilteredOutputStream(outputStream& os);
outputStream& getNextOutputStream();
void write(const value_type* const data, const size_type count);
void flush();
private:
outputStream& m_stream;
value_type m_previousChar;
};
/** A filtered input stream which stops when a specified sequence /** A filtered input stream which stops when a specified sequence
* is found (eof() method will return 'true'). * is found (eof() method will return 'true').
*/ */