// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EpicGames.Core; namespace UnrealBuildTool { /// /// Contains the name of an identifier. Individual objects are unique. /// class Identifier : IComparable { /// /// The name of this identifier /// string Name; /// /// Global map of name to identifier instance /// static ConcurrentDictionary NameToIdentifier = new ConcurrentDictionary(StringComparer.Ordinal); /// /// Constructor /// /// Name of this identifier private Identifier(string Name) { this.Name = Name; } /// /// Finds or adds an identifer with the given name /// /// Name of the identifier /// New Identifier instance public static Identifier FindOrAdd(string Name) { Identifier? Result; if(!NameToIdentifier.TryGetValue(Name, out Result)) { Identifier NewIdentifier = new Identifier(Name); if(NameToIdentifier.TryAdd(Name, NewIdentifier)) { Result = NewIdentifier; } else { Result = 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 ReferenceEquals(Other, null)? 1 : Name.CompareTo(Other.Name); } /// /// Formats this identifer as a string for debugging /// /// Name of this identifier public override string ToString() { return Name; } } /// /// Well known predefined identifiers /// 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 __building_module = Identifier.FindOrAdd("__building_module"); public static readonly Identifier __pragma = Identifier.FindOrAdd("__pragma"); } /// /// 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())); } } }