Bug 1329568 - Simple IsMediaMIMEType checker for strings - r?jya draft
authorGerald Squelart <gsquelart@mozilla.com>
Sun, 01 Jan 2017 08:46:34 +1100
changeset 460517 3a53b24e7dd9ef53f4b96ac85d81ebf0fc675ce5
parent 460516 87e23509063a8b497cf529b31d62bd12f6879476
child 460518 110ce695f7057f217500b21080fdc27fbde9fbad
push id41406
push usergsquelart@mozilla.com
push dateFri, 13 Jan 2017 06:23:59 +0000
reviewersjya
bugs1329568
milestone53.0a1
Bug 1329568 - Simple IsMediaMIMEType checker for strings - r?jya Inside dom/media, we really only deal with audio and video MIME types. IsMediaMIMEType will help check for that. Note that 'application' is an acceptable MIME major type, as some A/V contents do use it! E.g.: "application/ogg". IsMediaMIMEType is constexpr to allow its use in static_assert's, so we will be able to verify string literals at compile time. MozReview-Commit-ID: InBicRRUeiP
dom/media/VideoUtils.h
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -357,16 +357,86 @@ CreateTrackInfoWithMIMEType(const nsACSt
 
 // Try and create a TrackInfo with a given codec MIME type, and optional extra
 // parameters from a content type (its MIME type and codecs are ignored).
 UniquePtr<TrackInfo>
 CreateTrackInfoWithMIMETypeAndContentTypeExtraParameters(
   const nsACString& aCodecMIMEType,
   const MediaContentType& aContentType);
 
+namespace detail {
+
+// aString should start with aMajor + '/'.
+constexpr bool
+StartsWithMIMETypeMajor(const char* aString,
+                        const char* aMajor, size_t aMajorRemaining)
+{
+  return (aMajorRemaining == 0 && *aString == '/')
+         || (*aString == *aMajor
+             && StartsWithMIMETypeMajor(aString + 1,
+                                        aMajor + 1, aMajorRemaining - 1));
+}
+
+// aString should only contain [a-z0-9\-\.] and a final '\0'.
+constexpr bool
+EndsWithMIMESubtype(const char* aString, size_t aRemaining)
+{
+  return aRemaining == 0
+         || (((*aString >= 'a' && *aString <= 'z')
+              || (*aString >= '0' && *aString <= '9')
+              || *aString == '-'
+              || *aString == '.')
+             && EndsWithMIMESubtype(aString + 1, aRemaining - 1));
+}
+
+// Simple MIME-type literal string checker with a given (major) type.
+// Only accepts "{aMajor}/[a-z0-9\-\.]+".
+template <size_t MajorLengthPlus1>
+constexpr bool
+IsMIMETypeWithMajor(const char* aString, size_t aLength,
+                    const char (&aMajor)[MajorLengthPlus1])
+{
+  return aLength > MajorLengthPlus1 // Major + '/' + at least 1 char
+         && StartsWithMIMETypeMajor(aString, aMajor, MajorLengthPlus1 - 1)
+         && EndsWithMIMESubtype(aString + MajorLengthPlus1,
+                                aLength - MajorLengthPlus1);
+}
+
+} // namespace detail
+
+// Simple MIME-type string checker.
+// Only accepts lowercase "{application,audio,video}/[a-z0-9\-\.]+".
+// Add more if necessary.
+constexpr bool
+IsMediaMIMEType(const char* aString, size_t aLength)
+{
+  return detail::IsMIMETypeWithMajor(aString, aLength, "application")
+         || detail::IsMIMETypeWithMajor(aString, aLength, "audio")
+         || detail::IsMIMETypeWithMajor(aString, aLength, "video");
+}
+
+// Simple MIME-type string literal checker.
+// Only accepts lowercase "{application,audio,video}/[a-z0-9\-\.]+".
+// Add more if necessary.
+template <size_t LengthPlus1>
+constexpr bool
+IsMediaMIMEType(const char (&aString)[LengthPlus1])
+{
+  return IsMediaMIMEType(aString, LengthPlus1 - 1);
+}
+
+// Simple MIME-type string checker.
+// Only accepts lowercase "{application,audio,video}/[a-z0-9\-\.]+".
+// Add more if necessary.
+inline bool
+IsMediaMIMEType(const nsACString& aString)
+{
+  return IsMediaMIMEType(aString.Data(), aString.Length());
+}
+
 enum class StringListRangeEmptyItems
 {
   // Skip all empty items (empty string will process nothing)
   // E.g.: "a,,b" -> ["a", "b"], "" -> nothing
   Skip,
   // Process all, except if string is empty
   // E.g.: "a,,b" -> ["a", "", "b"], "" -> nothing
   ProcessEmptyItems,