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"
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 == '&' ||
c == '\'' || c == '*' || c == '+' || c == '-' || c == '.' ||
c == '^' || c == '_' || c == '`' || c == '|' || c == '~' ||
mozilla::IsAsciiAlphanumeric(c);
}
static inline bool IsHTTPQuotedStringTokenPoint(const char16_t c) {
return c == 0x9 || (c >= ' ' && c <= '~') || (c >= 0x80 && c <= 0xFF);
template<typename char_type>
static inline bool IsHTTPQuotedStringTokenPoint(const char_type c) {
return c == 0x9 || (c >= ' ' && c <= '~') || mozilla::IsNonAsciiLatin1(c);
}
}
/* static */ mozilla::UniquePtr<MimeType>
MimeType::Parse(const nsAString& aMimeType)
template<typename char_type>
/* 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
// Steps 1-2
const char16_t* pos = aMimeType.BeginReading();
const char16_t* end = aMimeType.EndReading();
const char_type* pos = aMimeType.BeginReading();
const char_type* end = aMimeType.EndReading();
while (pos < end && mozilla::IsAsciiWhitespace(*pos)) {
++pos;
}
@ -33,14 +36,14 @@ MimeType::Parse(const nsAString& aMimeType)
}
// Steps 3-4
const char16_t* typeStart = pos;
const char_type* typeStart = pos;
while (pos < end && *pos != '/') {
if (!IsHTTPTokenPoint(*pos)) {
return nullptr;
}
++pos;
}
const char16_t* typeEnd = pos;
const char_type* typeEnd = pos;
if (typeStart == typeEnd) {
return nullptr;
}
@ -54,8 +57,8 @@ MimeType::Parse(const nsAString& aMimeType)
++pos;
// Step 7-9
const char16_t* subtypeStart = pos;
const char16_t* subtypeEnd = nullptr;
const char_type* subtypeStart = pos;
const char_type* subtypeEnd = nullptr;
while (pos < end && *pos != ';') {
if (!IsHTTPTokenPoint(*pos)) {
// If we hit a whitespace, check that the rest of
@ -84,15 +87,15 @@ MimeType::Parse(const nsAString& aMimeType)
}
// Step 10
nsString type;
nsString subtype;
for (const char16_t* c = typeStart; c < typeEnd; ++c) {
nsTString<char_type> type;
nsTString<char_type> subtype;
for (const char_type* c = typeStart; c < typeEnd; ++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));
}
mozilla::UniquePtr<MimeType> mimeType(mozilla::MakeUnique<MimeType>(type, subtype));
mozilla::UniquePtr<TMimeType<char_type>> mimeType(mozilla::MakeUnique<TMimeType<char_type>>(type, subtype));
// Step 11
while (pos < end) {
@ -105,7 +108,7 @@ MimeType::Parse(const nsAString& aMimeType)
}
// Steps 11.3 and 11.4
nsString paramName;
nsTString<char_type> paramName;
bool paramNameHadInvalidChars = false;
while (pos < end && *pos != ';' && *pos != '=') {
if (!IsHTTPTokenPoint(*pos)) {
@ -186,7 +189,7 @@ MimeType::Parse(const nsAString& aMimeType)
} else {
const char16_t* paramValueStart = pos;
const char_type* paramValueStart = pos;
// Step 11.7.2.1
while (pos < end && *pos != ';') {
@ -200,13 +203,13 @@ MimeType::Parse(const nsAString& aMimeType)
}
// Step 11.7.2.2
const char16_t* paramValueEnd = pos - 1;
const char_type* paramValueEnd = pos - 1;
while (paramValueEnd >= paramValueStart &&
mozilla::IsAsciiWhitespace(*paramValueEnd)) {
--paramValueEnd;
}
for (const char16_t* c = paramValueStart; c <= paramValueEnd; ++c) {
for (const char_type* c = paramValueStart; c <= paramValueEnd; ++c) {
paramValue.Append(*c);
}
}
@ -224,8 +227,9 @@ MimeType::Parse(const nsAString& aMimeType)
return mimeType;
}
template<typename char_type>
void
MimeType::Serialize(nsAString& aOutput) const
TMimeType<char_type>::Serialize(nsTSubstring<char_type>& aOutput) const
{
aOutput.Assign(mType);
aOutput.AppendLiteral("/");
@ -239,8 +243,8 @@ MimeType::Serialize(nsAString& aOutput) const
aOutput.AppendLiteral("=");
if (value.mRequiresQuoting) {
aOutput.AppendLiteral("\"");
const char16_t* vcur = value.BeginReading();
const char16_t* vend = value.EndReading();
const char_type* vcur = value.BeginReading();
const char_type* vend = value.EndReading();
while (vcur < vend) {
if (*vcur == '"' || *vcur == '\\') {
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 "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:
class ParameterValue : public nsString
class ParameterValue : public nsTString<char_type>
{
public:
bool mRequiresQuoting;
@ -25,18 +31,22 @@ private:
{}
};
nsString mType;
nsString mSubtype;
nsDataHashtable<nsStringHashKey, ParameterValue> mParameters;
nsTArray<nsString> mParameterNames;
nsTString<char_type> mType;
nsTString<char_type> mSubtype;
nsDataHashtable<typename HashKeyType<char_type>::HashType, ParameterValue> mParameters;
nsTArray<nsTString<char_type>> mParameterNames;
public:
MimeType(const nsAString& aType, const nsAString& aSubtype)
TMimeType(const nsTSubstring<char_type>& aType, const nsTSubstring<char_type>& aSubtype)
: mType(aType), mSubtype(aSubtype)
{}
static mozilla::UniquePtr<MimeType> Parse(const nsAString& aStr);
void Serialize(nsAString& aStr) const;
static mozilla::UniquePtr<TMimeType<char_type>> Parse(const nsTSubstring<char_type>& aStr);
void Serialize(nsTSubstring<char_type>& aStr) const;
};
using MimeType = TMimeType<char16_t>;
using CMimeType = TMimeType<char>;
#endif // mozilla_dom_MimeType_h

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

@ -212,6 +212,17 @@ TEST(MimeType, DuplicateParameter2)
"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
#pragma warning(push)
#pragma warning(disable:4819)

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

@ -47,6 +47,15 @@ IsAscii(Char aChar)
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.
*