Bug 908413 - Make dom::MimeType a template to make it usable with nsCString r=hsivonen

Differential Revision: https://phabricator.services.mozilla.com/D5094

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Valentin Gosu 2018-09-07 05:41:29 +00:00
Родитель 86eda77a20
Коммит c4da49a35f
4 изменённых файлов: 71 добавлений и 32 удалений

Просмотреть файл

@ -2,26 +2,29 @@
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
namespace { namespace {
static inline bool IsHTTPTokenPoint(const char16_t c) { template<typename char_type>
static inline bool IsHTTPTokenPoint(const char_type c) {
return c == '!' || c == '#' || c == '$' || c == '%' || c == '&' || return c == '!' || c == '#' || c == '$' || c == '%' || c == '&' ||
c == '\'' || c == '*' || c == '+' || c == '-' || c == '.' || c == '\'' || c == '*' || c == '+' || c == '-' || c == '.' ||
c == '^' || c == '_' || c == '`' || c == '|' || c == '~' || c == '^' || c == '_' || c == '`' || c == '|' || c == '~' ||
mozilla::IsAsciiAlphanumeric(c); mozilla::IsAsciiAlphanumeric(c);
} }
static inline bool IsHTTPQuotedStringTokenPoint(const char16_t c) { template<typename char_type>
return c == 0x9 || (c >= ' ' && c <= '~') || (c >= 0x80 && c <= 0xFF); static inline bool IsHTTPQuotedStringTokenPoint(const char_type c) {
return c == 0x9 || (c >= ' ' && c <= '~') || mozilla::IsNonAsciiLatin1(c);
} }
} }
/* static */ mozilla::UniquePtr<MimeType> template<typename char_type>
MimeType::Parse(const nsAString& aMimeType) /* static */ mozilla::UniquePtr<TMimeType<char_type>>
TMimeType<char_type>::Parse(const nsTSubstring<char_type>& aMimeType)
{ {
// See https://mimesniff.spec.whatwg.org/#parsing-a-mime-type // See https://mimesniff.spec.whatwg.org/#parsing-a-mime-type
// Steps 1-2 // Steps 1-2
const char16_t* pos = aMimeType.BeginReading(); const char_type* pos = aMimeType.BeginReading();
const char16_t* end = aMimeType.EndReading(); const char_type* end = aMimeType.EndReading();
while (pos < end && mozilla::IsAsciiWhitespace(*pos)) { while (pos < end && mozilla::IsAsciiWhitespace(*pos)) {
++pos; ++pos;
} }
@ -33,14 +36,14 @@ MimeType::Parse(const nsAString& aMimeType)
} }
// Steps 3-4 // Steps 3-4
const char16_t* typeStart = pos; const char_type* typeStart = pos;
while (pos < end && *pos != '/') { while (pos < end && *pos != '/') {
if (!IsHTTPTokenPoint(*pos)) { if (!IsHTTPTokenPoint(*pos)) {
return nullptr; return nullptr;
} }
++pos; ++pos;
} }
const char16_t* typeEnd = pos; const char_type* typeEnd = pos;
if (typeStart == typeEnd) { if (typeStart == typeEnd) {
return nullptr; return nullptr;
} }
@ -54,8 +57,8 @@ MimeType::Parse(const nsAString& aMimeType)
++pos; ++pos;
// Step 7-9 // Step 7-9
const char16_t* subtypeStart = pos; const char_type* subtypeStart = pos;
const char16_t* subtypeEnd = nullptr; const char_type* subtypeEnd = nullptr;
while (pos < end && *pos != ';') { while (pos < end && *pos != ';') {
if (!IsHTTPTokenPoint(*pos)) { if (!IsHTTPTokenPoint(*pos)) {
// If we hit a whitespace, check that the rest of // If we hit a whitespace, check that the rest of
@ -84,15 +87,15 @@ MimeType::Parse(const nsAString& aMimeType)
} }
// Step 10 // Step 10
nsString type; nsTString<char_type> type;
nsString subtype; nsTString<char_type> subtype;
for (const char16_t* c = typeStart; c < typeEnd; ++c) { for (const char_type* c = typeStart; c < typeEnd; ++c) {
type.Append(ToLowerCaseASCII(*c)); type.Append(ToLowerCaseASCII(*c));
} }
for (const char16_t* c = subtypeStart; c < subtypeEnd; ++c) { for (const char_type* c = subtypeStart; c < subtypeEnd; ++c) {
subtype.Append(ToLowerCaseASCII(*c)); subtype.Append(ToLowerCaseASCII(*c));
} }
mozilla::UniquePtr<MimeType> mimeType(mozilla::MakeUnique<MimeType>(type, subtype)); mozilla::UniquePtr<TMimeType<char_type>> mimeType(mozilla::MakeUnique<TMimeType<char_type>>(type, subtype));
// Step 11 // Step 11
while (pos < end) { while (pos < end) {
@ -105,7 +108,7 @@ MimeType::Parse(const nsAString& aMimeType)
} }
// Steps 11.3 and 11.4 // Steps 11.3 and 11.4
nsString paramName; nsTString<char_type> paramName;
bool paramNameHadInvalidChars = false; bool paramNameHadInvalidChars = false;
while (pos < end && *pos != ';' && *pos != '=') { while (pos < end && *pos != ';' && *pos != '=') {
if (!IsHTTPTokenPoint(*pos)) { if (!IsHTTPTokenPoint(*pos)) {
@ -186,7 +189,7 @@ MimeType::Parse(const nsAString& aMimeType)
} else { } else {
const char16_t* paramValueStart = pos; const char_type* paramValueStart = pos;
// Step 11.7.2.1 // Step 11.7.2.1
while (pos < end && *pos != ';') { while (pos < end && *pos != ';') {
@ -200,13 +203,13 @@ MimeType::Parse(const nsAString& aMimeType)
} }
// Step 11.7.2.2 // Step 11.7.2.2
const char16_t* paramValueEnd = pos - 1; const char_type* paramValueEnd = pos - 1;
while (paramValueEnd >= paramValueStart && while (paramValueEnd >= paramValueStart &&
mozilla::IsAsciiWhitespace(*paramValueEnd)) { mozilla::IsAsciiWhitespace(*paramValueEnd)) {
--paramValueEnd; --paramValueEnd;
} }
for (const char16_t* c = paramValueStart; c <= paramValueEnd; ++c) { for (const char_type* c = paramValueStart; c <= paramValueEnd; ++c) {
paramValue.Append(*c); paramValue.Append(*c);
} }
} }
@ -224,8 +227,9 @@ MimeType::Parse(const nsAString& aMimeType)
return mimeType; return mimeType;
} }
template<typename char_type>
void void
MimeType::Serialize(nsAString& aOutput) const TMimeType<char_type>::Serialize(nsTSubstring<char_type>& aOutput) const
{ {
aOutput.Assign(mType); aOutput.Assign(mType);
aOutput.AppendLiteral("/"); aOutput.AppendLiteral("/");
@ -239,8 +243,8 @@ MimeType::Serialize(nsAString& aOutput) const
aOutput.AppendLiteral("="); aOutput.AppendLiteral("=");
if (value.mRequiresQuoting) { if (value.mRequiresQuoting) {
aOutput.AppendLiteral("\""); aOutput.AppendLiteral("\"");
const char16_t* vcur = value.BeginReading(); const char_type* vcur = value.BeginReading();
const char16_t* vend = value.EndReading(); const char_type* vend = value.EndReading();
while (vcur < vend) { while (vcur < vend) {
if (*vcur == '"' || *vcur == '\\') { if (*vcur == '"' || *vcur == '\\') {
aOutput.AppendLiteral("\\"); aOutput.AppendLiteral("\\");
@ -254,3 +258,8 @@ MimeType::Serialize(nsAString& aOutput) const
} }
} }
} }
template mozilla::UniquePtr<TMimeType<char16_t>> TMimeType<char16_t>::Parse(const nsTSubstring<char16_t>& aMimeType);
template mozilla::UniquePtr<TMimeType<char>> TMimeType<char>::Parse(const nsTSubstring<char>& aMimeType);
template void TMimeType<char16_t>::Serialize(nsTSubstring<char16_t>& aOutput) const;
template void TMimeType<char>::Serialize(nsTSubstring<char>& aOutput) const;

Просмотреть файл

@ -12,10 +12,16 @@
#include "nsDataHashtable.h" #include "nsDataHashtable.h"
#include "nsTArray.h" #include "nsTArray.h"
class MimeType final template<typename char_type> struct HashKeyType;
template<> struct HashKeyType<char16_t> { typedef nsStringHashKey HashType; };
template<> struct HashKeyType<char> { typedef nsCStringHashKey HashType; };
template <typename char_type>
class TMimeType final
{ {
private: private:
class ParameterValue : public nsString class ParameterValue : public nsTString<char_type>
{ {
public: public:
bool mRequiresQuoting; bool mRequiresQuoting;
@ -25,18 +31,22 @@ private:
{} {}
}; };
nsString mType; nsTString<char_type> mType;
nsString mSubtype; nsTString<char_type> mSubtype;
nsDataHashtable<nsStringHashKey, ParameterValue> mParameters; nsDataHashtable<typename HashKeyType<char_type>::HashType, ParameterValue> mParameters;
nsTArray<nsString> mParameterNames; nsTArray<nsTString<char_type>> mParameterNames;
public: public:
MimeType(const nsAString& aType, const nsAString& aSubtype) TMimeType(const nsTSubstring<char_type>& aType, const nsTSubstring<char_type>& aSubtype)
: mType(aType), mSubtype(aSubtype) : mType(aType), mSubtype(aSubtype)
{} {}
static mozilla::UniquePtr<MimeType> Parse(const nsAString& aStr); static mozilla::UniquePtr<TMimeType<char_type>> Parse(const nsTSubstring<char_type>& aStr);
void Serialize(nsAString& aStr) const;
void Serialize(nsTSubstring<char_type>& aStr) const;
}; };
using MimeType = TMimeType<char16_t>;
using CMimeType = TMimeType<char>;
#endif // mozilla_dom_MimeType_h #endif // mozilla_dom_MimeType_h

Просмотреть файл

@ -212,6 +212,17 @@ TEST(MimeType, DuplicateParameter2)
"Duplicate parameter #2"; "Duplicate parameter #2";
} }
TEST(MimeType, CString)
{
const auto in = NS_LITERAL_CSTRING("text/html;charset=();charset=GBK");
UniquePtr<CMimeType> parsed = CMimeType::Parse(in);
ASSERT_TRUE(parsed) << "Parsing succeeded";
nsCString out;
parsed->Serialize(out);
ASSERT_TRUE(out.Equals(NS_LITERAL_CSTRING("text/html;charset=\"()\""))) <<
"Duplicate parameter #2";
}
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4819) #pragma warning(disable:4819)

Просмотреть файл

@ -47,6 +47,15 @@ IsAscii(Char aChar)
return uc < 0x80; return uc < 0x80;
} }
template<typename Char>
constexpr bool
IsNonAsciiLatin1(Char aChar)
{
using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
auto uc = static_cast<UnsignedChar>(aChar);
return uc >= 0x80 && uc <= 0xFF;
}
/** /**
* Returns true iff |aChar| matches Ascii Whitespace. * Returns true iff |aChar| matches Ascii Whitespace.
* *