// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Concurrent; using EpicGames.Core; namespace UnrealBuildTool { /// /// Contains the name of an identifier. Individual objects are unique. /// class Identifier : IComparable { /// /// The name of this identifier /// readonly string _name; /// /// Global map of name to identifier instance /// static readonly ConcurrentDictionary s_nameToIdentifier = new(StringComparer.Ordinal); /// /// Constructor /// /// Name of this identifier private Identifier(string name) { _name = name; } /// /// Finds or adds an identifier with the given name /// /// Name of the identifier /// New Identifier instance public static Identifier FindOrAdd(string name) { if (!s_nameToIdentifier.TryGetValue(name, out Identifier? result)) { Identifier newIdentifier = new(name); if (s_nameToIdentifier.TryAdd(name, newIdentifier)) { result = newIdentifier; } else { result = s_nameToIdentifier[name]; } } return result; } /// /// Compares this identifier to another identifier /// /// Identifier to compare to /// Value indicating which identifier should sort first public int CompareTo(Identifier? other) { return other is null ? 1 : _name.CompareTo(other._name); } /// /// Formats this identifier as a string for debugging /// /// Name of this identifier public override string ToString() { return _name; } } /// /// Well known predefined identifiers /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Keep the names closer to definitions")] class Identifiers { public static readonly Identifier Include = Identifier.FindOrAdd("include"); public static readonly Identifier Define = Identifier.FindOrAdd("define"); public static readonly Identifier Undef = Identifier.FindOrAdd("undef"); public static readonly Identifier If = Identifier.FindOrAdd("if"); public static readonly Identifier Ifdef = Identifier.FindOrAdd("ifdef"); public static readonly Identifier Ifndef = Identifier.FindOrAdd("ifndef"); public static readonly Identifier Elif = Identifier.FindOrAdd("elif"); public static readonly Identifier Else = Identifier.FindOrAdd("else"); public static readonly Identifier Endif = Identifier.FindOrAdd("endif"); public static readonly Identifier Defined = Identifier.FindOrAdd("defined"); public static readonly Identifier Pragma = Identifier.FindOrAdd("pragma"); public static readonly Identifier Once = Identifier.FindOrAdd("once"); public static readonly Identifier Error = Identifier.FindOrAdd("error"); public static readonly Identifier Warning = Identifier.FindOrAdd("warning"); public static readonly Identifier __VA_ARGS__ = Identifier.FindOrAdd("__VA_ARGS__"); public static readonly Identifier __FILE__ = Identifier.FindOrAdd("__FILE__"); public static readonly Identifier __LINE__ = Identifier.FindOrAdd("__LINE__"); public static readonly Identifier __COUNTER__ = Identifier.FindOrAdd("__COUNTER__"); public static readonly Identifier Sizeof = Identifier.FindOrAdd("sizeof"); public static readonly Identifier Alignof = Identifier.FindOrAdd("alignof"); public static readonly Identifier __has_builtin = Identifier.FindOrAdd("__has_builtin"); public static readonly Identifier __has_feature = Identifier.FindOrAdd("__has_feature"); public static readonly Identifier __has_warning = Identifier.FindOrAdd("__has_warning"); public static readonly Identifier __building_module = Identifier.FindOrAdd("__building_module"); public static readonly Identifier __pragma = Identifier.FindOrAdd("__pragma"); public static readonly Identifier __builtin_return_address = Identifier.FindOrAdd("__builtin_return_address"); public static readonly Identifier __builtin_frame_address = Identifier.FindOrAdd("__builtin_frame_address"); public static readonly Identifier __has_attribute = Identifier.FindOrAdd("__has_attribute"); public static readonly Identifier __has_c_attribute = Identifier.FindOrAdd("__has_c_attribute"); public static readonly Identifier __has_cpp_attribute = Identifier.FindOrAdd("__has_cpp_attribute"); public static readonly Identifier __has_declspec_attribute = Identifier.FindOrAdd("__has_declspec_attribute"); public static readonly Identifier __has_keyword = Identifier.FindOrAdd("__has_keyword"); public static readonly Identifier __has_extension = Identifier.FindOrAdd("__has_extension"); public static readonly Identifier __has_include = Identifier.FindOrAdd("__has_include"); public static readonly Identifier __has_include_next = Identifier.FindOrAdd("__has_include_next"); public static readonly Identifier __is_identifier = Identifier.FindOrAdd("__is_identifier"); public static readonly Identifier __is_target_arch = Identifier.FindOrAdd("__is_target_arch"); } /// /// Helper functions for serialization /// static class IdentifierExtensionMethods { /// /// Read an identifier from a binary archive /// /// Reader to serialize data from /// Instance of the serialized identifier public static Identifier ReadIdentifier(this BinaryArchiveReader reader) { return reader.ReadObjectReference(() => Identifier.FindOrAdd(reader.ReadString()!))!; } /// /// Write an identifier to a binary archive /// /// Writer to serialize data to /// Identifier to write public static void WriteIdentifier(this BinaryArchiveWriter writer, Identifier? identifier) { writer.WriteObjectReference(identifier, () => writer.WriteString(identifier!.ToString())); } } }