// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using EpicGames.Core;
using EpicGames.UHT.Tokenizer;
using EpicGames.UHT.Types;
using EpicGames.UHT.Utils;
namespace EpicGames.UHT.Tables
{
///
/// Delegate for invoking structure default value sanitizer
///
///
///
///
///
public delegate bool UhtStructDefaultValueDelegate(UhtStructProperty property, IUhtTokenReader defaultValueReader, StringBuilder innerDefaultValue);
///
/// Options for structure default value sanitizer
///
[Flags]
public enum UhtStructDefaultValueOptions
{
///
/// No options
///
None = 0,
///
/// This method is to be invoked when there are no keyword matches found
///
Default = 1 << 2,
}
///
/// Helper methods for testing flags. These methods perform better than the generic HasFlag which hits
/// the GC and stalls.
///
public static class UhtStructDefaultValueOptionsExtensions
{
///
/// Test to see if any of the specified flags are set
///
/// Current flags
/// Flags to test for
/// True if any of the flags are set
public static bool HasAnyFlags(this UhtStructDefaultValueOptions inFlags, UhtStructDefaultValueOptions testFlags)
{
return (inFlags & testFlags) != 0;
}
///
/// Test to see if all of the specified flags are set
///
/// Current flags
/// Flags to test for
/// True if all the flags are set
public static bool HasAllFlags(this UhtStructDefaultValueOptions inFlags, UhtStructDefaultValueOptions testFlags)
{
return (inFlags & testFlags) == testFlags;
}
///
/// Test to see if a specific set of flags have a specific value.
///
/// Current flags
/// Flags to test for
/// Expected value of the tested flags
/// True if the given flags have a specific value.
public static bool HasExactFlags(this UhtStructDefaultValueOptions inFlags, UhtStructDefaultValueOptions testFlags, UhtStructDefaultValueOptions matchFlags)
{
return (inFlags & testFlags) == matchFlags;
}
}
///
/// Structure default value sanitizer attribute
///
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public sealed class UhtStructDefaultValueAttribute : Attribute
{
///
/// Name of the structure. Not required for default processor.
///
public string? Name { get; set; }
///
/// Options
///
public UhtStructDefaultValueOptions Options { get; set; } = UhtStructDefaultValueOptions.None;
}
///
/// Structure default value sanitizer
///
public struct UhtStructDefaultValue
{
///
/// The delegate to invoke
///
public UhtStructDefaultValueDelegate Delegate { get; set; }
}
///
/// Table of all structure default value specifiers
///
public class UhtStructDefaultValueTable
{
private readonly Dictionary _structDefaultValues = new();
private UhtStructDefaultValue? _default = null;
///
/// Fetch the default sanitizer
///
public UhtStructDefaultValue Default
{
get
{
if (_default == null)
{
throw new UhtIceException("No struct default value has been marked as default");
}
return (UhtStructDefaultValue)_default;
}
}
///
/// Return the structure default value associated with the given name
///
///
/// Structure default value handler
///
public bool TryGet(StringView name, out UhtStructDefaultValue structDefaultValue)
{
return _structDefaultValues.TryGetValue(name, out structDefaultValue);
}
///
/// Handle a structure default value sanitizer attribute
///
/// Method information
/// Found attribute
/// Thrown if the attribute isn't property defined
public void OnStructDefaultValueAttribute(MethodInfo methodInfo, UhtStructDefaultValueAttribute structDefaultValueAttribute)
{
if (String.IsNullOrEmpty(structDefaultValueAttribute.Name) && !structDefaultValueAttribute.Options.HasAnyFlags(UhtStructDefaultValueOptions.Default))
{
throw new UhtIceException("A struct default value attribute must have a name or be marked as default");
}
UhtStructDefaultValue structDefaultValue = new()
{
Delegate = (UhtStructDefaultValueDelegate)Delegate.CreateDelegate(typeof(UhtStructDefaultValueDelegate), methodInfo)
};
if (structDefaultValueAttribute.Options.HasAnyFlags(UhtStructDefaultValueOptions.Default))
{
if (_default != null)
{
throw new UhtIceException("Only one struct default value attribute dispatcher can be marked as default");
}
_default = structDefaultValue;
}
else if (!String.IsNullOrEmpty(structDefaultValueAttribute.Name))
{
_structDefaultValues.Add(new StringView(structDefaultValueAttribute.Name), structDefaultValue);
}
}
}
}