blob: f0d503e5e08e33376282358777b2d5e0c203ba63 [file] [log] [blame]
{#---
Macro for enum definition, and the declaration of associated functions.
---#}
{%- macro enum_decl(enum) %}
{%- set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
enum class {{enum_name}} : int32_t {
{%- for field in enum.fields %}
{%- if field.value %}
{{field.name}} = {{field.value|expression_to_text}},
{%- else %}
{{field.name}},
{%- endif %}
{%- endfor %}
};
inline std::ostream& operator<<(std::ostream& os, {{enum_name}} value) {
{%- if enum.fields %}
switch(value) {
{%- for _, values in enum.fields|groupby('numeric_value') %}
case {{enum_name}}::{{values[0].name}}:
return os << "{{enum_name}}::
{%- if values|length > 1 -%}
{{'{'}}
{%- endif -%}
{{values|map(attribute='name')|join(', ')}}
{%- if values|length > 1 -%}
{{'}'}}
{%- endif -%}
";
{%- endfor %}
default:
return os << "Unknown {{enum_name}} value: " << static_cast<int32_t>(value);
}
{%- else %}
return os << "Unknown {{enum_name}} value: " << static_cast<int32_t>(value);
{%- endif %}
}
{#- Returns true if the given enum value exists in this version of enum. #}
inline bool IsKnownEnumValue({{enum_name}} value) {
return {{enum|get_name_for_kind(internal=True,
flatten_nested_kind=True)}}::IsKnownValue(
static_cast<int32_t>(value));
}
{%- endmacro %}
{%- macro enum_data_decl(enum) %}
{%- set enum_name = enum|get_name_for_kind(flatten_nested_kind=True) %}
struct {{enum_name}}_Data {
public:
static bool constexpr kIsExtensible = {% if enum.extensible %}true{% else %}false{% endif %};
static bool IsKnownValue(int32_t value) {
{%- if enum.fields %}
switch (value) {
{%- for enum_field in enum.fields|groupby('numeric_value') %}
case {{enum_field[0]}}:
{%- endfor %}
return true;
}
{%- endif %}
return false;
}
static bool Validate(int32_t value,
mojo::internal::ValidationContext* validation_context) {
if (kIsExtensible || IsKnownValue(value))
return true;
ReportValidationError(validation_context,
mojo::internal::VALIDATION_ERROR_UNKNOWN_ENUM_VALUE);
return false;
}
};
{%- endmacro %}
{%- macro enum_hash(enum) %}
{%- set enum_name = enum|get_qualified_name_for_kind(
flatten_nested_kind=True) %}
template <>
struct hash<{{enum_name}}>
: public mojo::internal::EnumHashImpl<{{enum_name}}> {};
{%- endmacro %}
{%- macro enum_hash_blink(enum) %}
{%- set enum_name = enum|get_qualified_name_for_kind(
flatten_nested_kind=True, include_variant=False) %}
{%- set hash_fn_name = enum|wtf_hash_fn_name_for_enum %}
{# We need two unused enum values: #}
{%- set empty_value = -1000000 %}
{%- set deleted_value = -1000001 %}
{%- set empty_value_unused = "false" if empty_value in enum|all_enum_values else "true" %}
{%- set deleted_value_unused = "false" if empty_value in enum|all_enum_values else "true" %}
namespace WTF {
struct {{hash_fn_name}} {
static unsigned hash(const {{enum_name}}& value) {
typedef base::underlying_type<{{enum_name}}>::type utype;
return DefaultHash<utype>::Hash().hash(static_cast<utype>(value));
}
static bool equal(const {{enum_name}}& left, const {{enum_name}}& right) {
return left == right;
}
static const bool safeToCompareToEmptyOrDeleted = true;
};
template <>
struct DefaultHash<{{enum_name}}> {
using Hash = {{hash_fn_name}};
};
template <>
struct HashTraits<{{enum_name}}>
: public GenericHashTraits<{{enum_name}}> {
static_assert({{empty_value_unused}},
"{{empty_value}} is a reserved enum value");
static_assert({{deleted_value_unused}},
"{{deleted_value}} is a reserved enum value");
static const bool hasIsEmptyValueFunction = true;
static bool isEmptyValue(const {{enum_name}}& value) {
return value == static_cast<{{enum_name}}>({{empty_value}});
}
static void constructDeletedValue({{enum_name}}& slot, bool) {
slot = static_cast<{{enum_name}}>({{deleted_value}});
}
static bool isDeletedValue(const {{enum_name}}& value) {
return value == static_cast<{{enum_name}}>({{deleted_value}});
}
};
} // namespace WTF
{%- endmacro %}