зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
86eda77a20
Коммит
c4da49a35f
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
Загрузка…
Ссылка в новой задаче