Estimate generated size of parameterized field.
This commit is contained in:
parent
9df44078b8
commit
c446afddd4
@ -604,6 +604,40 @@ void parameter::generateImpl
|
||||
}
|
||||
|
||||
|
||||
size_t parameter::getGeneratedSize(const generationContext& ctx)
|
||||
{
|
||||
const string& name = m_name;
|
||||
const string& value = m_value->getBuffer();
|
||||
|
||||
const size_t bytesNeedingEncoding =
|
||||
value.length() - utility::stringUtils::countASCIIchars(value.begin(), value.end());
|
||||
|
||||
const size_t valueLength = value.length();
|
||||
|
||||
// Compute generated length in the very worst case
|
||||
|
||||
// Non-encoded parameter + value (worst case: quoting + QP)
|
||||
size_t len = name.length() + 1 /* = */ + 2 /* "" */ + 7 /* =?...?Q?...?= */
|
||||
+ m_value->getCharset().getName().length() + valueLength + bytesNeedingEncoding * 2 + 1 /* ; */;
|
||||
|
||||
// Encoded parameter + value
|
||||
const size_t maxEncodedValueLengthOnLine =
|
||||
ctx.getMaxLineLength() - 2 /* CRLF */ - NEW_LINE_SEQUENCE_LENGTH
|
||||
- name.length() - 5 /* *00*= */ - 1 /* ; */;
|
||||
|
||||
const size_t encodedValueLength = (valueLength + bytesNeedingEncoding * 2)
|
||||
+ m_value->getCharset().getName().length() + m_value->getLanguage().length() + 2 /* 2 x ' */;
|
||||
|
||||
const size_t numberOfSections = 1 /* worst case: generation starts at the end of a line */
|
||||
+ std::max(size_t(1), encodedValueLength / maxEncodedValueLengthOnLine);
|
||||
|
||||
len += numberOfSections * (name.length() + 5 /* *00*= */ + 1 /* ; */ + 2 /* CRLF */ + NEW_LINE_SEQUENCE_LENGTH) + encodedValueLength;
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const std::vector <shared_ptr <component> > parameter::getChildComponents()
|
||||
{
|
||||
std::vector <shared_ptr <component> > list;
|
||||
|
@ -85,6 +85,8 @@ public:
|
||||
void copyFrom(const component& other);
|
||||
parameter& operator=(const parameter& other);
|
||||
|
||||
size_t getGeneratedSize(const generationContext& ctx);
|
||||
|
||||
const std::vector <shared_ptr <component> > getChildComponents();
|
||||
|
||||
/** Return the name of this parameter.
|
||||
|
@ -359,6 +359,21 @@ void parameterizedHeaderField::generateImpl
|
||||
}
|
||||
|
||||
|
||||
size_t parameterizedHeaderField::getGeneratedSize(const generationContext& ctx)
|
||||
{
|
||||
size_t size = headerField::getGeneratedSize(ctx);
|
||||
|
||||
for (std::vector <shared_ptr <parameter> >::const_iterator
|
||||
it = m_params.begin() ; it != m_params.end() ; ++it)
|
||||
{
|
||||
size += 2; // "; "
|
||||
size += (*it)->getGeneratedSize(ctx);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
void parameterizedHeaderField::copyFrom(const component& other)
|
||||
{
|
||||
headerField::copyFrom(other);
|
||||
|
@ -179,6 +179,8 @@ public:
|
||||
*/
|
||||
const std::vector <shared_ptr <parameter> > getParameterList();
|
||||
|
||||
size_t getGeneratedSize(const generationContext& ctx);
|
||||
|
||||
const std::vector <shared_ptr <component> > getChildComponents();
|
||||
|
||||
private:
|
||||
|
@ -33,7 +33,9 @@ VMIME_TEST_SUITE_BEGIN(parameterTest)
|
||||
VMIME_TEST(testParse)
|
||||
VMIME_TEST(testParseRFC2231)
|
||||
VMIME_TEST(testGenerate)
|
||||
VMIME_TEST(testGetGeneratedSize)
|
||||
VMIME_TEST(testGenerateRFC2231)
|
||||
VMIME_TEST(testGetGeneratedSizeRFC2231)
|
||||
VMIME_TEST(testNonStandardEncodedParam)
|
||||
VMIME_TEST(testParseNonSignificantWS)
|
||||
VMIME_TEST(testEncodeTSpecials)
|
||||
@ -76,6 +78,25 @@ VMIME_TEST_SUITE_BEGIN(parameterTest)
|
||||
};
|
||||
|
||||
|
||||
const vmime::string generateParameter
|
||||
(const vmime::parameter& param,
|
||||
const vmime::generationContext& ctx,
|
||||
const vmime::size_t maxLineLength = 0) const
|
||||
{
|
||||
vmime::generationContext ctx2(ctx);
|
||||
|
||||
if (maxLineLength != 0)
|
||||
ctx2.setMaxLineLength(maxLineLength);
|
||||
|
||||
std::ostringstream oss;
|
||||
vmime::utility::outputStreamAdapter adapter(oss);
|
||||
|
||||
param.generate(ctx2, adapter);
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
#define FIELD_VALUE(f) (f.getValue()->generate())
|
||||
#define PARAM_VALUE(p, n) (p.getParameterAt(n)->getValue().generate())
|
||||
#define PARAM_NAME(p, n) (p.getParameterAt(n)->getName())
|
||||
@ -270,6 +291,20 @@ VMIME_TEST_SUITE_BEGIN(parameterTest)
|
||||
VASSERT_EQ("2b", "F: X; param1=\"va\\\\lue\\\"1\"", p2b.generate());
|
||||
}
|
||||
|
||||
void testGetGeneratedSize()
|
||||
{
|
||||
vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
|
||||
|
||||
vmime::parameter p1("param1", "value1");
|
||||
VASSERT("1", p1.getGeneratedSize(ctx) >= generateParameter(p1, ctx).length());
|
||||
|
||||
vmime::parameter p2a("param1", "value1a;value1b");
|
||||
VASSERT("2&", p2a.getGeneratedSize(ctx) >= generateParameter(p2a, ctx).length());
|
||||
|
||||
vmime::parameter p2b("param1", "va\\lue\"1");
|
||||
VASSERT("1", p2b.getGeneratedSize(ctx) >= generateParameter(p2b, ctx).length());
|
||||
}
|
||||
|
||||
void testGenerateRFC2231()
|
||||
{
|
||||
// Extended parameter with charset specifier
|
||||
@ -403,6 +438,111 @@ VMIME_TEST_SUITE_BEGIN(parameterTest)
|
||||
p5.generate(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047));
|
||||
}
|
||||
|
||||
void testGetGeneratedSizeRFC2231()
|
||||
{
|
||||
vmime::generationContext ctx(vmime::generationContext::getDefaultContext());
|
||||
|
||||
// Extended parameter with charset specifier
|
||||
vmime::parameter p1(
|
||||
"param1",
|
||||
vmime::word("value 1\xe9", vmime::charset("charset"))
|
||||
);
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING);
|
||||
VASSERT("1.no-encoding", p1.getGeneratedSize(ctx) >= generateParameter(p1, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY);
|
||||
VASSERT("1.rfc2047", p1.getGeneratedSize(ctx) >= generateParameter(p1, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY);
|
||||
VASSERT("1.rfc2231", p1.getGeneratedSize(ctx) >= generateParameter(p1, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047);
|
||||
VASSERT("1.both", p1.getGeneratedSize(ctx) >= generateParameter(p1, ctx).length());
|
||||
|
||||
// Value that spans on multiple lines
|
||||
vmime::parameter p2(
|
||||
"param1",
|
||||
vmime::word(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
vmime::charset("charset")
|
||||
)
|
||||
);
|
||||
|
||||
ctx.setMaxLineLength(25);
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING);
|
||||
VASSERT("2.no-encoding", p2.getGeneratedSize(ctx) >= generateParameter(p2, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY);
|
||||
VASSERT("2.rfc2047", p2.getGeneratedSize(ctx) >= generateParameter(p2, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY);
|
||||
VASSERT("2.rfc2231", p2.getGeneratedSize(ctx) >= generateParameter(p2, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047);
|
||||
VASSERT("2.both", p2.getGeneratedSize(ctx) >= generateParameter(p2, ctx).length());
|
||||
|
||||
// Non-ASCII parameter value
|
||||
vmime::parameter p3(
|
||||
"param1",
|
||||
vmime::word(
|
||||
"δσσσσσσσσσσσσσσσσσσσσδσδα δσαδσδσαδσαδασδασ δσαδασδσα δσαδασδσα δασδασδασ δασαχφδδσα 2008.doc",
|
||||
vmime::charset("utf-8")
|
||||
)
|
||||
);
|
||||
|
||||
ctx.setMaxLineLength(vmime::generationContext::getDefaultContext().getMaxLineLength());
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING);
|
||||
VASSERT("3.no-encoding", p3.getGeneratedSize(ctx) >= generateParameter(p3, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY);
|
||||
VASSERT("3.rfc2047", p3.getGeneratedSize(ctx) >= generateParameter(p3, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY);
|
||||
VASSERT("3.rfc2231", p3.getGeneratedSize(ctx) >= generateParameter(p3, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047);
|
||||
VASSERT("3.both", p3.getGeneratedSize(ctx) >= generateParameter(p3, ctx).length());
|
||||
|
||||
// No encoding needed
|
||||
vmime::parameter p4(
|
||||
"param1",
|
||||
vmime::word("va lue", vmime::charset("charset"))
|
||||
);
|
||||
|
||||
ctx.setMaxLineLength(vmime::generationContext::getDefaultContext().getMaxLineLength());
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING);
|
||||
VASSERT("4.no-encoding", p4.getGeneratedSize(ctx) >= generateParameter(p4, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY);
|
||||
VASSERT("4.rfc2047", p4.getGeneratedSize(ctx) >= generateParameter(p4, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY);
|
||||
VASSERT("4.rfc2231", p4.getGeneratedSize(ctx) >= generateParameter(p4, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047);
|
||||
VASSERT("4.both", p4.getGeneratedSize(ctx) >= generateParameter(p4, ctx).length());
|
||||
|
||||
// Language specification
|
||||
vmime::parameter p5(
|
||||
"param1",
|
||||
vmime::word("This is ***fun***", vmime::charset("us-ascii"), "en-us")
|
||||
);
|
||||
|
||||
ctx.setMaxLineLength(vmime::generationContext::getDefaultContext().getMaxLineLength());
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_NO_ENCODING);
|
||||
VASSERT("5.no-encoding", p5.getGeneratedSize(ctx) >= generateParameter(p5, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2047_ONLY);
|
||||
VASSERT("5.rfc2047", p5.getGeneratedSize(ctx) >= generateParameter(p5, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_ONLY);
|
||||
VASSERT("5.rfc2231", p5.getGeneratedSize(ctx) >= generateParameter(p5, ctx).length());
|
||||
|
||||
ctx.setEncodedParameterValueMode(vmime::generationContext::PARAMETER_VALUE_RFC2231_AND_RFC2047);
|
||||
VASSERT("5.both", p5.getGeneratedSize(ctx) >= generateParameter(p5, ctx).length());
|
||||
}
|
||||
|
||||
void testNonStandardEncodedParam()
|
||||
{
|
||||
// This syntax is non-standard (expressly prohibited
|
||||
|
Loading…
Reference in New Issue
Block a user