using Luban.Job.Common.RawDefs; using Luban.Job.Common.Utils; using System; using System.Collections.Generic; using System.Linq; using Bright.Collections; namespace Luban.Job.Common.Defs { public class DefEnum : DefTypeBase { public class Item { public string Name { get; set; } public string Value { get; set; } public string Alias { get; set; } public string AliasOrName => string.IsNullOrWhiteSpace(Alias) ? Name : Alias; public int IntValue { get; set; } public string Comment { get; set; } public string EscapeComment => DefUtil.EscapeCommentByCurrentLanguage(Comment); public Dictionary Tags { get; set; } public bool HasTag(string attrName) { return Tags != null && Tags.ContainsKey(attrName); } public string GetTag(string attrName) { return Tags != null && Tags.TryGetValue(attrName, out var value) ? value : null; } } public bool IsFlags { get; } public bool IsUniqueItemId { get; } public List Items { get; } = new List(); private readonly Dictionary _nameOrAlias2Value = new(); private readonly Dictionary _vaule2Name = new(); public bool TryValueByNameOrAlias(string name, out int value) { return _nameOrAlias2Value.TryGetValue(name, out value); } public int GetValueByNameOrAlias(string name) { // TODO flags ? if (!name.Contains('|')) { return GetBasicValueByNameOrAlias(name); } int combindValue = 0; foreach (var s in name.Split('|')) { combindValue |= GetBasicValueByNameOrAlias(s.Trim()); } return combindValue; } private int GetBasicValueByNameOrAlias(string name) { if (_nameOrAlias2Value.TryGetValue(name, out var value)) { return value; } else if (int.TryParse(name, out value)) { if (!_vaule2Name.ContainsKey(value)) { throw new Exception($"{value} 不是 enum:'{FullName}'的有效枚举值"); } return value; } else { throw new Exception($"'{name}' 不是enum:'{FullName}'的有效枚举值"); } } public DefEnum(PEnum e) { Name = e.Name; Namespace = e.Namespace; IsFlags = e.IsFlags; IsUniqueItemId = e.IsUniqueItemId; Comment = e.Comment; Tags = DefUtil.ParseAttrs(e.Tags); foreach (var item in e.Items) { Items.Add(new Item { Name = item.Name, Alias = item.Alias, Value = item.Value, Comment = string.IsNullOrWhiteSpace(item.Comment) ? item.Alias : item.Comment, Tags = DefUtil.ParseAttrs(item.Tags), }); } } public override void Compile() { var fullName = FullName; int lastEnumValue = -1; var names = new HashSet(); foreach (var item in Items) { string value = item.Value.ToLower(); if (!names.Add(item.Name)) { throw new Exception($"enum:'{fullName}' 字段:'{item.Name}' 重复"); } if (string.IsNullOrEmpty(value)) { // A, item.IntValue = ++lastEnumValue; item.Value = item.IntValue.ToString(); } else if (int.TryParse(item.Value, out var v)) { // A = 5, item.IntValue = v; lastEnumValue = v; } else if (value.StartsWith("0x")) { if (int.TryParse(value.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out var x)) { item.IntValue = x; lastEnumValue = x; } else { throw new Exception($"enum:'{fullName}' 枚举名:'{item.Name}' value:'{item.Value}' 非法"); } } else if (IsFlags) { // D = A | B | C, string[] itemNames = item.Value.Split('|').Select(s => s.Trim()).ToArray(); foreach (var n in itemNames) { var index = Items.FindIndex(i => i.Name == n); if (index < 0) { throw new Exception($"enum:'{fullName}' 枚举名:'{item.Name}' 值:'{item.Value}' 非法"); } item.IntValue |= Items[index].IntValue; } } else { throw new Exception($"enum:'{fullName}' 枚举名:'{item.Name}' value:'{item.Value}' 非法"); } if (!string.IsNullOrWhiteSpace(item.Name) && !_nameOrAlias2Value.TryAdd(item.Name, item.IntValue)) { throw new Exception($"enum:'{fullName}' 枚举名:'{Name}' 重复"); } if (!string.IsNullOrWhiteSpace(item.Alias) && !_nameOrAlias2Value.TryAdd(item.Alias, item.IntValue)) { throw new Exception($"enum:'{fullName}' 枚举名:'{Name}' alias:'{item.Alias}' 重复"); } if (_vaule2Name.TryGetValue(item.IntValue, out var itemName)) { if (IsUniqueItemId) { throw new Exception($"enum:'{fullName}' 枚举值:{item.IntValue} 重复. 枚举名:'{itemName}' <=> '{item.Name}'"); } } else { _vaule2Name.Add(item.IntValue, item.Name); } } } } }