// 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()));
}
}
}