// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using EpicGames.Core;
namespace UnrealBuildTool
{
///
/// Identifier for a config file key, including information about the hierarchy used to read it
///
[DebuggerDisplay("{Name}")]
class ConfigDependencyKey : IEquatable
{
///
/// The config hierarchy type
///
public ConfigHierarchyType Type;
///
/// Project directory to read config files from
///
public DirectoryReference? ProjectDir;
///
/// The platform being built
///
public UnrealTargetPlatform Platform;
///
/// The section name
///
public string SectionName;
///
/// The key name
///
public string KeyName;
///
/// Constructor
///
/// The config hierarchy type
/// Project directory to read config files from
/// The platform being built
/// The section name
/// The key name
public ConfigDependencyKey(ConfigHierarchyType Type, DirectoryReference? ProjectDir, UnrealTargetPlatform Platform, string SectionName, string KeyName)
{
this.Type = Type;
this.ProjectDir = ProjectDir;
this.Platform = Platform;
this.SectionName = SectionName;
this.KeyName = KeyName;
}
///
/// Construct a key from an archive
///
/// Archive to read from
public ConfigDependencyKey(BinaryArchiveReader Reader)
{
Type = (ConfigHierarchyType)Reader.ReadInt();
ProjectDir = Reader.ReadDirectoryReference();
Platform = Reader.ReadUnrealTargetPlatform();
SectionName = Reader.ReadString()!;
KeyName = Reader.ReadString()!;
}
///
/// Writes this key to an archive
///
/// Archive to write to
public void Write(BinaryArchiveWriter Writer)
{
Writer.WriteInt((int)Type);
Writer.WriteDirectoryReference(ProjectDir);
Writer.WriteUnrealTargetPlatform(Platform);
Writer.WriteString(SectionName);
Writer.WriteString(KeyName);
}
///
/// Tests whether this key is equal to another object
///
/// The object to compare to
/// True if the keys are equal, false otherwise
public override bool Equals(object? Other)
{
return (Other is ConfigDependencyKey key) && Equals(key);
}
///
/// Tests whether this key is equal to another key
///
/// The key to compare to
/// True if the keys are equal, false otherwise
public bool Equals(ConfigDependencyKey? Other)
{
return Other is not null && Type == Other.Type && ProjectDir == Other.ProjectDir && Platform == Other.Platform && SectionName == Other.SectionName && KeyName == Other.KeyName;
}
///
/// Gets a hash code for this object
///
/// Hash code for the object
public override int GetHashCode()
{
int Hash = 17;
Hash = (Hash * 31) + Type.GetHashCode();
Hash = (Hash * 31) + ((ProjectDir == null) ? 0 : ProjectDir.GetHashCode());
Hash = (Hash * 31) + Platform.GetHashCode();
Hash = (Hash * 31) + SectionName.GetHashCode();
Hash = (Hash * 31) + KeyName.GetHashCode();
return Hash;
}
}
///
/// Stores a list of config key/value pairs that have been read
///
class ConfigValueTracker
{
///
/// The dependencies list
///
readonly IReadOnlyDictionary?> Dependencies;
///
/// Constructor
///
public ConfigValueTracker(IReadOnlyDictionary?> ConfigValues)
{
Dependencies = new Dictionary?>(ConfigValues);
}
///
/// Construct an object from an archive on disk
///
/// Archive to read from
public ConfigValueTracker(BinaryArchiveReader Reader)
{
Dependencies = Reader.ReadDictionary(() => new ConfigDependencyKey(Reader), () => (IReadOnlyList?)Reader.ReadList(() => Reader.ReadString()))!;
}
///
/// Write the dependencies object to disk
///
/// Archive to write to
public void Write(BinaryArchiveWriter Writer)
{
Writer.WriteDictionary(Dependencies, Key => Key.Write(Writer), Value => Writer.WriteList(Value, x => Writer.WriteString(x)));
}
///
/// Checks whether the list of dependencies is still valid
///
///
public bool IsValid()
{
foreach (KeyValuePair?> Pair in Dependencies)
{
// Read the appropriate hierarchy
ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(Pair.Key.Type, Pair.Key.ProjectDir, Pair.Key.Platform);
// Get the value(s) associated with this key
IReadOnlyList? NewValues;
Hierarchy.TryGetValues(Pair.Key.SectionName, Pair.Key.KeyName, out NewValues);
// Check if they're different
if (Pair.Value == null)
{
if (NewValues != null)
{
return false;
}
}
else
{
if (NewValues == null || !Enumerable.SequenceEqual(Pair.Value, NewValues, StringComparer.Ordinal))
{
return false;
}
}
}
return true;
}
}
}