212 lines
8.6 KiB
C++
212 lines
8.6 KiB
C++
// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
#ifndef WVCDM_UTIL_HLS_ATTRIBUTE_LIST_H_
|
|
#define WVCDM_UTIL_HLS_ATTRIBUTE_LIST_H_
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <map>
|
|
#include <ostream>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "wv_class_utils.h"
|
|
|
|
namespace wvutil {
|
|
// An HLS Attribute List is a loosely defined HLS tag value
|
|
// type representing a dictionary of attribute name-value pairs.
|
|
// No attribute name may appear twice in a valid HLS Attribute
|
|
// List.
|
|
//
|
|
// When serialized, an HLS attribute list appears as a comma
|
|
// separated list of <name>=<value> pairs, without any line breaks,
|
|
// and whitespace only within quoted string attribute values.
|
|
//
|
|
// The HLS specification defines them as context sensitive-types,
|
|
// as the format of certain value types are ambiguous with other
|
|
// value types (ex. something that looks like a hex sequence could
|
|
// actually be an enum string). The exact value types of attributes
|
|
// depends on the HLS tag.
|
|
//
|
|
// This implementation is intended to be context free when parsing.
|
|
// Internally, value will be assigned a type based on their
|
|
// appearance to the most restrictive type; however, accessing as a
|
|
// particular type will be allowed so long as they match the format
|
|
// that type. The only exception to this is quoted strings, which
|
|
// are fully unambiguous with all other types.
|
|
//
|
|
// The standard HLS attribute list allows for UTF-8 encoded unicode
|
|
// characters; however, for Widevine's use case, we only allow
|
|
// basic ASCII.
|
|
//
|
|
// This class is based on RFC 8216 section 4.2.
|
|
class HlsAttributeList {
|
|
public:
|
|
enum ValueType {
|
|
kUnsetType = 0,
|
|
// HLS integers are a sequence of 1 to 20 base10 digits
|
|
// values, which must fit into an unsigned 64-bit integer.
|
|
// Note:
|
|
// All integers can appear as an enum string.
|
|
// All integers can appear as floats; however, precision
|
|
// restrictions may limit ability to parse accurately.
|
|
kIntegerType,
|
|
// HLS hex sequence are a sequence of 1 or more upper case
|
|
// hexadecimal digits, with the prefix "0x" or "0X".
|
|
// Note:
|
|
// All hex sequences can appear as an enum string.
|
|
// Certain hex sequences can appear as a resolution.
|
|
kHexSequenceType,
|
|
// HLS float and sign float are a sequence of base10 digits
|
|
// with a possible leading negative sign ('-') and at most one
|
|
// decimal point ('.').
|
|
// Note:
|
|
// All floats can appear as an enum string.
|
|
// Certain floats can appear are an integer.
|
|
kFloatType,
|
|
// For simplicity, signed and unsigned floats are internally
|
|
// treated as the same.
|
|
kSignedFloatType = kFloatType, // Aliasing
|
|
// HLS quoted strings are a sequence of printable characters
|
|
// (except a double quote), or space characters, contained within
|
|
// a pair of double quotes.
|
|
// Note: Quote string are unambiguous with all other types.
|
|
kQuotedStringType,
|
|
// HLS enum strings are a sequence of any printable characters
|
|
// (except quotes or commas) and do not contain whitespace.
|
|
// Note:
|
|
// Certain enum strings can appear as integers, floats, hex
|
|
// sequences or resolutions.
|
|
kEnumStringType,
|
|
// HLS resolutions are a pair of base10 integers (similar to
|
|
// integer types) separated by an 'x' character.
|
|
// Note:
|
|
// All resolutions can appear as enum strings
|
|
// Certain resolutions can appear as hex sequences.
|
|
kResolutionType,
|
|
};
|
|
static const char* ValueTypeToString(ValueType type);
|
|
|
|
// Checks if the provided |name| is valid HLS attribute name.
|
|
static bool IsValidName(const std::string& name);
|
|
|
|
// Checks if the provided |value| is a valid HLS enumerated
|
|
// string.
|
|
static bool IsValidEnumStringValue(const std::string& value);
|
|
// Checks if the provided |value| is an allowed content
|
|
// of a quote string (i.e., |value| is the portion that is
|
|
// to be contained within the double quotes).
|
|
static bool IsValidQuotedStringValue(const std::string& value);
|
|
|
|
// Validator for an HLS unsigned integer representation.
|
|
// Checks that the value representation |value_rep| conforms
|
|
// to HLS requirements for a serialized integer.
|
|
static bool IsValidIntegerRep(const std::string& value_rep);
|
|
// Parses the provided |integer_rep| as an HLS integer, assign
|
|
// the parsed integer to |value|.
|
|
static bool ParseInteger(const std::string& integer_rep, uint64_t* value);
|
|
|
|
HlsAttributeList() = default;
|
|
WVCDM_DEFAULT_COPY_AND_MOVE(HlsAttributeList);
|
|
|
|
// == Basic Accessors ==
|
|
bool IsEmpty() const { return members_.empty(); }
|
|
size_t Count() const { return members_.size(); }
|
|
void Clear() { members_.clear(); }
|
|
|
|
// == Value Getters ==
|
|
|
|
// Returns a list of attribute names.
|
|
std::vector<std::string> GetNames() const;
|
|
// Returns true if the provided attribute |name| is contained
|
|
// within list.
|
|
bool Contains(const std::string& name) const;
|
|
|
|
// Checks if the provided attribute |name| could be the
|
|
// specified |type|.
|
|
// Certain value types are ambiguous; so they may be marked
|
|
// internally as one type, but are still valid forms of a
|
|
// different type.
|
|
bool IsType(const std::string& name, ValueType type) const;
|
|
|
|
// Gets the attribute value for the provided attribute |name|,
|
|
// assigning the deserialized value to the output parameter(s).
|
|
//
|
|
// If a type is internally stored as a different type, but the format
|
|
// matches the requested type, it will be allowed.
|
|
//
|
|
// Returns true if the attribute value was successfully obtained;
|
|
// false otherwise (attribute does not exist, or the value could
|
|
// not be parsed as the specified type).
|
|
bool GetEnumString(const std::string& name, std::string* value) const;
|
|
bool GetQuotedString(const std::string& name, std::string* value) const;
|
|
bool GetHexSequence(const std::string& name, std::string* value) const;
|
|
bool GetHexSequence(const std::string& name,
|
|
std::vector<uint8_t>* value) const;
|
|
bool GetInteger(const std::string& name, uint64_t* value) const;
|
|
bool GetFloat(const std::string& name, double* value) const;
|
|
bool GetResolution(const std::string& name, uint64_t* width,
|
|
uint64_t* height) const;
|
|
|
|
// == Value Setters ==
|
|
|
|
// The value setters attempt to serializes the provided value
|
|
// into an HLS attribute value format of the type indicated
|
|
// by the method name. These methods will overwrite any existing
|
|
// attribute of the same name.
|
|
// Setting will be rejected if |name| is not a valid HLS attribute
|
|
// name, or if the provided |value| is valid (only applicable to
|
|
// certain types).
|
|
bool SetEnumString(const std::string& name, const std::string& value);
|
|
bool SetQuotedString(const std::string& name, const std::string& value);
|
|
// Note: This implementation will use lower "0x" prefix for
|
|
// hex sequences.
|
|
bool SetHexSequence(const std::string& name, const std::string& value);
|
|
bool SetHexSequence(const std::string& name,
|
|
const std::vector<uint8_t>& value);
|
|
bool SetInteger(const std::string& name, uint64_t value);
|
|
bool SetFloat(const std::string& name, double value);
|
|
bool SetResolution(const std::string& name, uint64_t width, uint64_t height);
|
|
|
|
// Removes the specified attribute. Returns true if the attribute
|
|
// was removed; false otherwise.
|
|
bool Remove(const std::string& name);
|
|
|
|
// == Parsing / Serialization ==
|
|
|
|
// Attempts to parse the provided HLS Attribute List.
|
|
// Always clears the existing contents, even if the attribute
|
|
// list cannot be parsed.
|
|
//
|
|
// Internally, values are not parsed, but checked to see which
|
|
// type they resemble. This does not restrict accessing them
|
|
// as different types.
|
|
//
|
|
// Returns true if successfully parsed; false otherwise.
|
|
bool Parse(const std::string& hls_attr_list_rep);
|
|
|
|
// Serializes the contents of the HLS attribute list into a
|
|
// valid HLS attribute list form.
|
|
std::string Serialize() const;
|
|
bool SerializeToStream(std::ostream* out) const;
|
|
|
|
// Internally, values are stored in their serialized form
|
|
// in case their value is ambiguous between two or more types.
|
|
// The assigned ValueType is intended to be a hint for improve
|
|
// access speeds.
|
|
using ValueInfo =
|
|
std::pair</* type hint */ ValueType, /* value rep */ std::string>;
|
|
|
|
private:
|
|
// Internal utility to obtain the value info.
|
|
// Silently returns null if the name does not exist.
|
|
const ValueInfo* GetInfo(const std::string& name) const;
|
|
|
|
// Values in |members_| will always be validated before assigned.
|
|
std::map</* name */ std::string, ValueInfo> members_;
|
|
}; // class HlsAttributeList
|
|
} // namespace wvutil
|
|
#endif // WVCDM_UTIL_HLS_ATTRIBUTE_LIST_H_
|