diff --git a/RogueLibsCore/Names/CustomName.cs b/RogueLibsCore/Names/CustomName.cs
index e2145f00..ceae90cb 100644
--- a/RogueLibsCore/Names/CustomName.cs
+++ b/RogueLibsCore/Names/CustomName.cs
@@ -6,21 +6,26 @@ namespace RogueLibsCore
///
/// The implementation of the interface, used by the . Provides properties for getting and setting the 8 default languages' localization texts.
///
- public class CustomName : IName
+ public class CustomName : IName, IUsesNameContainer
{
internal CustomName(string name, string type, string english)
{
Name = name;
Type = type;
- English = english;
+ container = english;
}
internal CustomName(string name, string type, IEnumerable> dictionary)
{
Name = name;
Type = type;
- foreach (KeyValuePair pair in dictionary)
- if (pair.Value is not null)
- translations[pair.Key] = pair.Value;
+
+ if (dictionary is IUsesNameContainer nameCont)
+ container = NameContainer.Clone(nameCont.GetNameContainer());
+ else
+ {
+ foreach (KeyValuePair entry in dictionary)
+ container = NameContainer.Set(container, entry.Key, entry.Value);
+ }
}
///
@@ -65,20 +70,19 @@ internal CustomName(string name, string type, IEnumerable
public string? Korean { get => this[LanguageCode.Korean]; set => this[LanguageCode.Korean] = value; }
- private readonly Dictionary translations = new Dictionary(1);
+ private object? container;
+ object? IUsesNameContainer.GetNameContainer() => container;
+
///
public string? this[LanguageCode language]
{
- get => translations.TryGetValue(language, out string str) ? str : null;
- set
- {
- if (value is not null) translations[language] = value;
- else translations.Remove(language);
- }
+ get => NameContainer.Get(container, language);
+ set => container = NameContainer.Set(container, language, value);
}
///
- public IEnumerator> GetEnumerator() => translations.GetEnumerator();
+ public IEnumerator> GetEnumerator()
+ => NameContainer.Enumerate(container);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
diff --git a/RogueLibsCore/Names/CustomNameInfo.cs b/RogueLibsCore/Names/CustomNameInfo.cs
index a6f7eebe..b79fbea1 100644
--- a/RogueLibsCore/Names/CustomNameInfo.cs
+++ b/RogueLibsCore/Names/CustomNameInfo.cs
@@ -1,24 +1,20 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Linq;
namespace RogueLibsCore
{
///
/// The implementation of the interface. Provides properties for getting and setting the 8 default languages' localization texts.
///
- public struct CustomNameInfo : IName
+ public struct CustomNameInfo : IName, IUsesNameContainer
{
///
/// Initializes a new instance of structure with the specified localization text.
///
/// The English localization text.
public CustomNameInfo(string english)
- {
- if (english is null) throw new ArgumentNullException(nameof(english));
- _texts = new Dictionary(1) { [LanguageCode.English] = english };
- }
+ => container = english ?? throw new ArgumentNullException(nameof(english));
///
/// Initializes a new instance of structure with localization texts from the specified .
///
@@ -26,11 +22,13 @@ public CustomNameInfo(string english)
public CustomNameInfo(IEnumerable> dictionary)
{
if (dictionary is null) throw new ArgumentNullException(nameof(dictionary));
- IEnumerable> pairs = dictionary.ToArray();
- _texts = new Dictionary(pairs.Count());
- foreach (KeyValuePair pair in pairs)
- if (pair.Value != null)
- _texts[pair.Key] = pair.Value;
+ if (dictionary is IUsesNameContainer name)
+ container = NameContainer.Clone(name.GetNameContainer());
+ else
+ {
+ foreach (KeyValuePair entry in dictionary)
+ container = NameContainer.Set(container, entry.Key, entry.Value);
+ }
}
///
@@ -66,22 +64,19 @@ public CustomNameInfo(IEnumerable> dictionary
///
public string? Korean { readonly get => this[LanguageCode.Korean]; set => this[LanguageCode.Korean] = value; }
- private Dictionary _texts;
- private Dictionary Texts => _texts ??= new Dictionary(1);
+ private object? container;
+ readonly object? IUsesNameContainer.GetNameContainer() => container;
+
///
public string? this[LanguageCode language]
{
- readonly get => _texts != null && _texts.TryGetValue(language, out string str) ? str : null;
- set
- {
- if (value != null) Texts[language] = value;
- else _texts?.Remove(language);
- }
+ readonly get => NameContainer.Get(container, language);
+ set => container = NameContainer.Set(container, language, value);
}
///
public IEnumerator> GetEnumerator()
- => (_texts ?? Enumerable.Empty>()).GetEnumerator();
+ => NameContainer.Enumerate(container);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
diff --git a/RogueLibsCore/Names/Localization/LanguageService.cs b/RogueLibsCore/Names/Localization/LanguageService.cs
index ae6e79b0..e7d6fb52 100644
--- a/RogueLibsCore/Names/Localization/LanguageService.cs
+++ b/RogueLibsCore/Names/Localization/LanguageService.cs
@@ -78,18 +78,20 @@ public static LanguageCode FallBack
public static string? GetLanguageName(LanguageCode code)
=> languageNames.TryGetValue(code, out string? name) ? name : null;
///
- /// Adds the specified to the game, and sets its language .
+ /// Adds the specified to the game, and returns its registered value.
///
/// The language name to add into the game.
- /// The language code that will be used to represent the language.
- public static void RegisterLanguageCode(string languageName, LanguageCode code)
+ /// The language code that will be used to represent the language.
+ public static LanguageCode RegisterLanguageCode(string languageName)
{
if (languageName is null) throw new ArgumentNullException(nameof(languageName));
if (languages.ContainsKey(languageName))
throw new ArgumentException($"The specified {nameof(languageName)} is already taken.", nameof(languageName));
+ LanguageCode code = (LanguageCode)languages.Count;
languages.Add(languageName, code);
languageNames.Add(code, languageName);
+ return code;
}
///
diff --git a/RogueLibsCore/Names/NameContainer.cs b/RogueLibsCore/Names/NameContainer.cs
new file mode 100644
index 00000000..b7d46272
--- /dev/null
+++ b/RogueLibsCore/Names/NameContainer.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using JetBrains.Annotations;
+
+namespace RogueLibsCore
+{
+ internal static class NameContainer
+ {
+ public static string? Get(object? container, LanguageCode code)
+ {
+ if (container is null) return null;
+ if (container is string text) return code == LanguageCode.English ? text : null;
+
+ if (container is string?[] array) return GetArray(array, code);
+ return GetDict((Dictionary)container, code);
+
+ static string? GetArray(string?[] array, LanguageCode code)
+ => (int)code < array.Length ? array[(int)code] : null;
+
+ static string? GetDict(Dictionary dict, LanguageCode code)
+ => dict.TryGetValue(code, out string? value) ? value : null;
+ }
+
+ [MustUseReturnValue]
+ public static object? Set(object? container, LanguageCode code, string? value)
+ {
+ if (container is null)
+ return value is null ? null : SetNew(code, value);
+ if (container is string text)
+ return SetString(text, code, value);
+ if (container is string?[] array)
+ return SetArray(array, code, value);
+ return SetDict((Dictionary)container, code, value);
+ }
+ private static object SetNew(LanguageCode code, string value)
+ {
+ if (code == LanguageCode.English) return value;
+ if ((int)code < 32)
+ {
+ string?[] array = new string?[LengthCeil8((int)code)];
+ array[(int)code] = value;
+ return array;
+ }
+ return new Dictionary { [code] = value };
+ }
+ private static object? SetString(string container, LanguageCode code, string? value)
+ {
+ if (code == LanguageCode.English) return value;
+ if (value is null) return container;
+ if ((int)code < 32)
+ {
+ string?[] array = new string?[LengthCeil8((int)code)];
+ array[(int)LanguageCode.English] = container;
+ array[(int)code] = value;
+ return array;
+ }
+ return new Dictionary
+ {
+ [LanguageCode.English] = container,
+ [code] = value,
+ };
+ }
+ private static object SetArray(string?[] array, LanguageCode code, string? value)
+ {
+ if ((int)code >= array.Length)
+ {
+ if (value is null) return array;
+ if ((int)code >= 32)
+ {
+ Dictionary dict = new();
+ for (int i = 0; i < array.Length; i++)
+ if (array[i] is not null)
+ dict[(LanguageCode)i] = array[i]!;
+ dict[code] = value;
+ return dict;
+ }
+ Array.Resize(ref array, LengthCeil8((int)code));
+ }
+ array[(int)code] = value;
+ return array;
+ }
+ private static object SetDict(Dictionary dict, LanguageCode code, string? value)
+ {
+ if (value is not null)
+ dict[code] = value;
+ else dict.Remove(code);
+ return dict;
+ }
+
+ public static object? Clone(object? container)
+ {
+ if (container is null) return null;
+ if (container is string) return container;
+ if (container is string?[] array) return array.ToArray();
+ return ((Dictionary)container).ToDictionary(static p => p);
+ }
+
+ public static IEnumerator> Enumerate(object? container)
+ {
+ if (container is null) yield break;
+ if (container is string text)
+ {
+ yield return new KeyValuePair(LanguageCode.English, text);
+ }
+ else if (container is string?[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i] is not null)
+ yield return new KeyValuePair((LanguageCode)i, array[i]!);
+ }
+ }
+ else
+ {
+ foreach (KeyValuePair entry in (Dictionary)container)
+ yield return entry;
+ }
+ }
+
+ private static int LengthCeil8(int num)
+ => (num + 8) & ~0b111;
+
+ }
+ internal interface IUsesNameContainer
+ {
+ object? GetNameContainer();
+ }
+}